Repository: AliceLR/megazeux Branch: master Commit: 73ce4e679fc4 Files: 1307 Total size: 11.6 MB Directory structure: gitextract_vpyz_01n/ ├── .gitattributes ├── .github/ │ └── workflows/ │ └── main.yml ├── .gitignore ├── .valgrindrc ├── BUILDING.md ├── LICENSE ├── Makefile ├── README.md ├── arch/ │ ├── 3ds/ │ │ ├── CONFIG.3DS │ │ ├── Makefile.in │ │ ├── README.md │ │ ├── audio.c │ │ ├── event.c │ │ ├── event.h │ │ ├── keyboard.c │ │ ├── keyboard.h │ │ ├── pad.config │ │ ├── pad.config.sdl12 │ │ ├── pad.config.sdl2 │ │ ├── platform.c │ │ ├── platform.h │ │ ├── render.cpp │ │ ├── render.h │ │ ├── shader_2d.g.pica │ │ ├── shader_2d.v.pica │ │ ├── shader_playfield.g.pica │ │ ├── shader_playfield.v.pica │ │ └── thread.h │ ├── LICENSE.3rd │ ├── LICENSE.CC0 │ ├── LICENSE.DJGPP │ ├── LICENSE.LGPL2 │ ├── LICENSE.MPL2 │ ├── LICENSE.Newlib │ ├── README │ ├── amiga/ │ │ ├── CONFIG.AMIGA │ │ ├── MZXRun │ │ ├── Makefile.in │ │ ├── MegaZeux │ │ ├── MegaZeux.info │ │ └── README │ ├── android/ │ │ ├── CONFIG.ANDROID │ │ ├── Makefile.deps │ │ ├── Makefile.in │ │ ├── README.md │ │ ├── SDL2-page-sizes.patch │ │ ├── config_types.h │ │ ├── libogg-Android.mk │ │ ├── libvorbis-Android.mk │ │ └── project/ │ │ ├── app/ │ │ │ ├── build.gradle │ │ │ ├── jni/ │ │ │ │ ├── Android.mk │ │ │ │ ├── Application.mk │ │ │ │ └── main/ │ │ │ │ └── Android.mk │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ └── main/ │ │ │ ├── AndroidManifest.xml │ │ │ ├── java/ │ │ │ │ ├── net/ │ │ │ │ │ └── digitalmzx/ │ │ │ │ │ └── megazeux/ │ │ │ │ │ ├── GameActivity.java │ │ │ │ │ └── MainActivity.java │ │ │ │ └── org/ │ │ │ │ └── libsdl/ │ │ │ │ └── app/ │ │ │ │ ├── HIDDevice.java │ │ │ │ ├── HIDDeviceBLESteamController.java │ │ │ │ ├── HIDDeviceManager.java │ │ │ │ ├── HIDDeviceUSB.java │ │ │ │ ├── SDL.java │ │ │ │ ├── SDLActivity.java │ │ │ │ ├── SDLAudioManager.java │ │ │ │ ├── SDLControllerManager.java │ │ │ │ └── SDLSurface.java │ │ │ └── res/ │ │ │ ├── raw/ │ │ │ │ └── readme │ │ │ └── values/ │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle/ │ │ │ └── wrapper/ │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ │ ├── gradle.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── compat.inc │ ├── darwin/ │ │ ├── MZXRun.plist │ │ ├── Makefile.arch │ │ ├── Makefile.in │ │ ├── MegaZeux.plist │ │ ├── README.md │ │ ├── bin/ │ │ │ └── otool │ │ ├── bundle.sh │ │ ├── dmg.sh │ │ └── lipo.sh │ ├── djgpp/ │ │ ├── CONFIG.DJGPP │ │ ├── Makefile.in │ │ ├── audio.c │ │ ├── driver_sb.h │ │ ├── event.c │ │ ├── interrupt.S │ │ ├── platform.c │ │ ├── platform_djgpp.h │ │ ├── render_ega.c │ │ ├── render_svga.c │ │ └── thread.h │ ├── dreamcast/ │ │ ├── CONFIG.DC │ │ ├── Makefile.in │ │ ├── audio.c │ │ ├── event.c │ │ ├── pad.config │ │ ├── platform.c │ │ ├── render.c │ │ ├── render_fb.c │ │ └── thread.h │ ├── emscripten/ │ │ ├── CONFIG.HTML5 │ │ ├── Makefile.in │ │ ├── README │ │ ├── emzip.c │ │ ├── web/ │ │ │ ├── package.json │ │ │ ├── res/ │ │ │ │ ├── docs/ │ │ │ │ │ └── emscripten_readme.txt │ │ │ │ ├── index.html │ │ │ │ └── mzxrun_loader.js │ │ │ ├── rollup.config.js │ │ │ └── src/ │ │ │ ├── index.js │ │ │ ├── storage.js │ │ │ ├── storage_emscripten.js │ │ │ ├── util.js │ │ │ └── zip.js │ │ └── whitelist.json │ ├── gp2x/ │ │ ├── Makefile.in │ │ ├── README │ │ └── pad.config │ ├── install.inc │ ├── lha.inc │ ├── manifest.sh │ ├── mingw/ │ │ ├── Makefile.in │ │ ├── checkres-readme.txt │ │ ├── checkres.bat │ │ ├── directx.bat │ │ ├── installer.nsi │ │ └── pefix.c │ ├── msvc/ │ │ ├── Core.vcxproj │ │ ├── Core.vcxproj.filters │ │ ├── Editor.vcxproj │ │ ├── Editor.vcxproj.filters │ │ ├── MZXRun.vcxproj │ │ ├── MZXRun.vcxproj.filters │ │ ├── MegaZeux.sln │ │ ├── MegaZeux.vcxproj │ │ ├── MegaZeux.vcxproj.filters │ │ ├── README.txt │ │ ├── config.h │ │ ├── dirent.h │ │ ├── msvc.h │ │ ├── update_version.cmd │ │ ├── win32time.c │ │ └── win32time.h │ ├── nds/ │ │ ├── CONFIG.NDS │ │ ├── Makefile │ │ ├── Makefile.in │ │ ├── README │ │ ├── arm7/ │ │ │ ├── Makefile │ │ │ └── source/ │ │ │ └── arm7main.c │ │ ├── audio.c │ │ ├── dlmalloc.c │ │ ├── dlmalloc.h │ │ ├── event.c │ │ ├── event.h │ │ ├── evq.c │ │ ├── evq.h │ │ ├── extmem.c │ │ ├── extmem.h │ │ ├── gen_protected_palette.py │ │ ├── internals_notes.txt │ │ ├── malloc_opts.h │ │ ├── pad.config │ │ ├── platform.c │ │ ├── platform.h │ │ ├── ram.c │ │ ├── ram.h │ │ ├── render.c │ │ └── render.h │ ├── nds-blocksds/ │ │ ├── CONFIG.NDS │ │ └── Makefile.in │ ├── none/ │ │ └── Makefile.in │ ├── pandora/ │ │ ├── Makefile.in │ │ └── README │ ├── psp/ │ │ ├── CONFIG.PSP │ │ ├── Makefile.in │ │ ├── README │ │ ├── pad.config │ │ └── platform.c │ ├── psvita/ │ │ ├── CONFIG.PSVITA │ │ ├── Makefile.in │ │ ├── README.md │ │ ├── pad.config.sdl12 │ │ └── sce_sys/ │ │ └── livearea/ │ │ └── contents/ │ │ └── template.xml │ ├── switch/ │ │ ├── CONFIG.SWITCH │ │ ├── Makefile.in │ │ └── pad.config │ ├── unix/ │ │ ├── Makefile.in │ │ ├── README │ │ ├── megazeux.desktop │ │ ├── megazeux.metainfo.xml │ │ └── mzxrun.desktop │ ├── wii/ │ │ ├── CONFIG.WII │ │ ├── Makefile.in │ │ ├── README │ │ ├── audio.c │ │ ├── event.c │ │ ├── meta.xml │ │ ├── network.cpp │ │ ├── pad.config │ │ ├── pad.config.sdl │ │ ├── pad.config.sdl2 │ │ ├── platform.c │ │ ├── render_gx.c │ │ ├── render_xfb.c │ │ └── thread.h │ ├── wiiu/ │ │ ├── CONFIG.WIIU │ │ ├── Makefile.in │ │ ├── meta.xml │ │ └── pad.config │ ├── xcode/ │ │ ├── MZXRun/ │ │ │ ├── Assets.xcassets/ │ │ │ │ └── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Info.plist │ │ ├── MegaZeux/ │ │ │ ├── Assets.xcassets/ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Base.lproj/ │ │ │ │ └── MainMenu.xib │ │ │ └── Info.plist │ │ ├── MegaZeux.xcodeproj/ │ │ │ ├── project.pbxproj │ │ │ └── project.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── README.md │ │ ├── config.h │ │ └── update_version.sh │ └── zip.inc ├── assets/ │ ├── ascii.chr │ ├── blank.chr │ ├── default.chr │ ├── edit.chr │ ├── gamecontrollerdb.txt │ ├── glsl/ │ │ ├── README.md │ │ ├── cursor.frag │ │ ├── cursor.vert │ │ ├── mouse.frag │ │ ├── mouse.vert │ │ ├── scaler.vert │ │ ├── scalers/ │ │ │ ├── crt-wave.frag │ │ │ ├── crt.frag │ │ │ ├── emboss.frag │ │ │ ├── epx.frag │ │ │ ├── greyscale.frag │ │ │ ├── hqscale.frag │ │ │ ├── hqscale.vert │ │ │ ├── nearest.frag │ │ │ ├── sai.frag │ │ │ ├── semisoft.frag │ │ │ ├── sepia.frag │ │ │ └── simple.frag │ │ ├── tilemap.frag │ │ ├── tilemap.smzx.frag │ │ └── tilemap.vert │ ├── help.fil │ ├── smzx.chr │ ├── smzx.pal │ └── smzx2.chr ├── config.sh ├── config.txt ├── contrib/ │ ├── archicons/ │ │ └── README │ ├── gdm2s3m/ │ │ ├── COPYING │ │ ├── CREDITS │ │ ├── README │ │ ├── build.bat │ │ ├── doc/ │ │ │ ├── gdm.txt │ │ │ ├── s3m-form.txt │ │ │ └── s3m_effects.txt │ │ └── src/ │ │ ├── Makefile.in │ │ ├── error.c │ │ ├── error.h │ │ ├── gdm.c │ │ ├── gdm.h │ │ ├── gdm2s3m.c │ │ ├── gdm2s3m.h │ │ ├── s3m.c │ │ ├── s3m.h │ │ ├── types.h │ │ ├── utility.c │ │ └── utility.h │ ├── hlp2html/ │ │ ├── README.md │ │ ├── fonts.css │ │ ├── style.css │ │ └── style_color.css │ ├── icons/ │ │ ├── Makefile.in │ │ ├── icon.rc │ │ └── old/ │ │ ├── logicow/ │ │ │ ├── ghostblue.rc │ │ │ └── ghostred.rc │ │ └── quantump/ │ │ ├── quantump.icns │ │ └── quantump.rc │ ├── infback9/ │ │ ├── LICENSE │ │ ├── README │ │ ├── infback9.c │ │ ├── infback9.h │ │ ├── inffix9.h │ │ ├── inflate9.h │ │ ├── inftree9.c │ │ ├── inftree9.h │ │ └── zutil.h │ ├── khash/ │ │ └── khash.h │ ├── libmodplug/ │ │ ├── AUTHORS │ │ ├── COPYING │ │ ├── ChangeLog │ │ ├── NEWS │ │ ├── README │ │ ├── TODO │ │ └── src/ │ │ ├── Makefile.in │ │ ├── fastmix.cpp │ │ ├── libmodplug/ │ │ │ ├── it_defs.h │ │ │ ├── sndfile.h │ │ │ └── stdafx.h │ │ ├── load_669.cpp │ │ ├── load_amf.cpp │ │ ├── load_dsm.cpp │ │ ├── load_far.cpp │ │ ├── load_gdm.cpp │ │ ├── load_it.cpp │ │ ├── load_med.cpp │ │ ├── load_mod.cpp │ │ ├── load_mtm.cpp │ │ ├── load_okt.cpp │ │ ├── load_s3m.cpp │ │ ├── load_stm.cpp │ │ ├── load_ult.cpp │ │ ├── load_wav.cpp │ │ ├── load_xm.cpp │ │ ├── mmcmp.cpp │ │ ├── modplug.cpp │ │ ├── modplug.h │ │ ├── snd_dsp.cpp │ │ ├── snd_flt.cpp │ │ ├── snd_fx.cpp │ │ ├── sndfile.cpp │ │ ├── sndmix.cpp │ │ └── tables.h │ ├── libxmp/ │ │ ├── Makefile.megazeux │ │ ├── Makefile.megazeux-gen │ │ ├── README │ │ ├── README.megazeux.md │ │ ├── docs/ │ │ │ ├── COPYING │ │ │ ├── CREDITS │ │ │ └── Changelog │ │ ├── include/ │ │ │ └── xmp.h │ │ ├── mzx-gen.sh │ │ └── src/ │ │ ├── callbackio.h │ │ ├── common.h │ │ ├── control.c │ │ ├── dataio.c │ │ ├── effects.c │ │ ├── effects.h │ │ ├── extras.c │ │ ├── extras.h │ │ ├── far_extras.c │ │ ├── far_extras.h │ │ ├── filetype.c │ │ ├── filter.c │ │ ├── flow.c │ │ ├── format.c │ │ ├── format.h │ │ ├── hio.c │ │ ├── hio.h │ │ ├── hmn_extras.c │ │ ├── hmn_extras.h │ │ ├── lfo.c │ │ ├── lfo.h │ │ ├── list.h │ │ ├── load.c │ │ ├── load_helpers.c │ │ ├── loaders/ │ │ │ ├── 669_load.c │ │ │ ├── amf_load.c │ │ │ ├── asylum_load.c │ │ │ ├── common.c │ │ │ ├── far_load.c │ │ │ ├── flt_load.c │ │ │ ├── gdm_load.c │ │ │ ├── hmn_load.c │ │ │ ├── ice_load.c │ │ │ ├── iff.c │ │ │ ├── iff.h │ │ │ ├── it.h │ │ │ ├── it_load.c │ │ │ ├── itsex.c │ │ │ ├── loader.h │ │ │ ├── med.h │ │ │ ├── med2_load.c │ │ │ ├── med3_load.c │ │ │ ├── med4_load.c │ │ │ ├── mmd1_load.c │ │ │ ├── mmd3_load.c │ │ │ ├── mmd_common.c │ │ │ ├── mod.h │ │ │ ├── mod_load.c │ │ │ ├── mtm_load.c │ │ │ ├── okt_load.c │ │ │ ├── s3m.h │ │ │ ├── s3m_load.c │ │ │ ├── sample.c │ │ │ ├── st_load.c │ │ │ ├── stm_load.c │ │ │ ├── ult_load.c │ │ │ ├── xm.h │ │ │ └── xm_load.c │ │ ├── md5.c │ │ ├── md5.h │ │ ├── mdataio.h │ │ ├── med_extras.c │ │ ├── med_extras.h │ │ ├── memio.c │ │ ├── memio.h │ │ ├── mix_all.c │ │ ├── mixer.c │ │ ├── mixer.h │ │ ├── period.c │ │ ├── period.h │ │ ├── player.c │ │ ├── player.h │ │ ├── precomp_lut.h │ │ ├── read_event.c │ │ ├── rng.c │ │ ├── rng.h │ │ ├── scan.c │ │ ├── smix.c │ │ ├── tempfile.h │ │ ├── virtual.c │ │ └── virtual.h │ ├── mzvplay/ │ │ └── mzvplay.txt │ ├── patches/ │ │ ├── libmodplug/ │ │ │ ├── 01-libmodplug-0.8.9.0-fix-looping.diff │ │ │ ├── 02-libmodplug-0.8.9.0-fix-X86_Convert32To24.diff │ │ │ ├── 03-libmodplug-0.8.9.0-if0-dead-code-make-globals-static.diff │ │ │ ├── 04-libmodplug-0.8.9.0-remove-unused-loaders.diff │ │ │ ├── 05-libmodplug-0.8.9.0-fix-type-punning-warnings.diff │ │ │ ├── 06-libmodplug-0.8.9.0-remove-unused-defines.diff │ │ │ ├── 07-libmodplug-0.8.9.0-misc-warning-fixes.diff │ │ │ ├── 08-libmodplug-0.8.9.0-remove-set-but-unused-variables.diff │ │ │ ├── 09-libmodplug-0.8.9.0-remove-dll-defines.diff │ │ │ ├── 10-libmodplug-0.8.9.0-fix-far-volume.diff │ │ │ ├── 11-libmodplug-0.8.9.0-fix-okt-order-list.diff │ │ │ ├── 12-libmodplug-0.8.9.0-add-mod-cd61-magic.diff │ │ │ ├── 13-libmodplug-0.8.9.0-fix-669-tempo.diff │ │ │ ├── 14-libmodplug-0.8.9.0-add-gdm-loader.diff │ │ │ └── readme.txt │ │ └── libxmp/ │ │ ├── 01-libxmp-mzx-integration.patch │ │ ├── 02-libxmp-mzx-remove-extra-formats.patch │ │ ├── 03-libxmp-real-max-srate.patch │ │ └── README │ └── rad/ │ ├── README.md │ ├── opal.cpp │ ├── player20.cpp │ ├── test_nested_riffs.rad │ ├── test_nested_riffs_transpose.rad │ └── validate20.cpp ├── debian/ │ ├── README │ ├── binary.lintian-overrides │ ├── changelog │ ├── compat │ ├── control │ ├── copyright │ ├── docs │ ├── megazeux.manpages │ └── rules ├── docs/ │ ├── SDLkeys.txt │ ├── STYLE.md │ ├── WIPHelp.txt │ ├── changelog.txt │ ├── counter_list.txt │ ├── cycles_and_commands.txt │ ├── exotic.txt │ ├── exotic_translations.txt │ ├── fileform.html │ ├── idle_direction_oddities.txt │ ├── info_mzx.txt │ ├── joystick.html │ ├── keycodes.html │ ├── macro.txt │ ├── megazeux.1 │ ├── mzxhelp.html │ ├── old/ │ │ ├── betatest.txt │ │ ├── filef200.txt │ │ ├── filef268.txt │ │ ├── fileform.txt │ │ ├── megazeux.doc │ │ ├── mzm.txt │ │ └── port.txt │ ├── platform_matrix.html │ └── push_and_transport.txt ├── megazeux.spec ├── scripts/ │ ├── ajs-buildscripts/ │ │ ├── README │ │ ├── amiga.sh │ │ ├── build-rev.sh │ │ ├── build.sh │ │ ├── darwin.sh │ │ ├── global.sh │ │ ├── gp2x.sh │ │ ├── nds.sh │ │ ├── psp.sh │ │ ├── wii.sh │ │ ├── windows-x64.sh │ │ ├── windows-x86.sh │ │ └── zip-split-debug.sh │ ├── buildscripts/ │ │ ├── 1_PrepareReleaseEnvironment.bat │ │ ├── 2_CreateReleases.bat │ │ ├── 3_PackageReleases.bat │ │ ├── 4_UploadReleases.bat │ │ ├── README.md │ │ ├── mzx-build.sh │ │ ├── mzx-check.sh │ │ ├── mzx-init.sh │ │ ├── mzx-nightly.sh │ │ ├── mzx-scripts/ │ │ │ ├── build.sh │ │ │ ├── caverns.sh │ │ │ ├── common-dkp.sh │ │ │ ├── common-mingw.sh │ │ │ ├── common.sh │ │ │ ├── crlf.sh │ │ │ ├── patches/ │ │ │ │ └── pspge.patch │ │ │ ├── platforms/ │ │ │ │ ├── 3ds.sh │ │ │ │ ├── android.sh │ │ │ │ ├── default.sh │ │ │ │ ├── djgpp.sh │ │ │ │ ├── dreamcast.sh │ │ │ │ ├── emscripten.sh │ │ │ │ ├── nds-blocksds.sh │ │ │ │ ├── nds.sh │ │ │ │ ├── psp.sh │ │ │ │ ├── psvita.sh │ │ │ │ ├── source.sh │ │ │ │ ├── switch.sh │ │ │ │ ├── wii.sh │ │ │ │ ├── wiiu.sh │ │ │ │ ├── windows-x64.sh │ │ │ │ └── windows-x86.sh │ │ │ ├── setup.sh │ │ │ ├── updates.sh │ │ │ ├── uploads.sh │ │ │ └── version.sh │ │ ├── mzx-updates.sh │ │ └── mzx-upload.sh │ ├── deps/ │ │ ├── Makefile │ │ ├── Makefile.djgpp.in │ │ ├── Makefile.linux-msan.in │ │ ├── Makefile.macos.in │ │ ├── Makefile.mingw.in │ │ ├── Makefile.xcode.in │ │ ├── README.md │ │ ├── fix-vorbis-1.3.7-build-framework.patch │ │ └── panther_SDL2_fixes.patch │ └── pkg/ │ ├── README.md │ ├── alpine/ │ │ └── APKBUILD │ ├── archlinux/ │ │ ├── PKGBUILD.template │ │ └── update-pkgbuild.sh │ ├── flatpak/ │ │ └── com.digitalmzx.MegaZeux.yml │ ├── macports/ │ │ └── Portfile │ ├── nix/ │ │ └── default.nix │ └── voidlinux/ │ ├── template │ └── update ├── src/ │ ├── Makefile.in │ ├── SDLmzx.h │ ├── about.c │ ├── about.h │ ├── audio/ │ │ ├── audio.c │ │ ├── audio.h │ │ ├── audio_mikmod.c │ │ ├── audio_mikmod.h │ │ ├── audio_modplug.cpp │ │ ├── audio_modplug.h │ │ ├── audio_openmpt.c │ │ ├── audio_openmpt.h │ │ ├── audio_pcs.c │ │ ├── audio_pcs.h │ │ ├── audio_reality.cpp │ │ ├── audio_reality.h │ │ ├── audio_sdl.c │ │ ├── audio_struct.h │ │ ├── audio_vorbis.c │ │ ├── audio_vorbis.h │ │ ├── audio_wav.c │ │ ├── audio_wav.h │ │ ├── audio_xmp.c │ │ ├── audio_xmp.h │ │ ├── driver_sdl3.c │ │ ├── ext.c │ │ ├── ext.h │ │ ├── sampled_stream.cpp │ │ ├── sampled_stream.h │ │ ├── sfx.c │ │ └── sfx.h │ ├── block.c │ ├── block.h │ ├── board.c │ ├── board.h │ ├── board_struct.h │ ├── caption.c │ ├── caption.h │ ├── compat.h │ ├── configure.c │ ├── configure.h │ ├── const.h │ ├── core.c │ ├── core.h │ ├── core_task.c │ ├── core_task.h │ ├── counter.c │ ├── counter.h │ ├── counter_struct.h │ ├── data.c │ ├── data.h │ ├── editor/ │ │ ├── Makefile.in │ │ ├── ansi.c │ │ ├── ansi.h │ │ ├── block.c │ │ ├── block.h │ │ ├── board.c │ │ ├── board.h │ │ ├── buffer.c │ │ ├── buffer.h │ │ ├── buffer_struct.h │ │ ├── char_ed.c │ │ ├── char_ed.h │ │ ├── clipboard.h │ │ ├── clipboard_carbon.c │ │ ├── clipboard_cocoa.m │ │ ├── clipboard_null.c │ │ ├── clipboard_sdl2.c │ │ ├── clipboard_win32.c │ │ ├── clipboard_x11.c │ │ ├── configure.c │ │ ├── configure.h │ │ ├── debug.c │ │ ├── debug.h │ │ ├── edit.c │ │ ├── edit.h │ │ ├── edit_di.c │ │ ├── edit_di.h │ │ ├── edit_export.c │ │ ├── edit_export.h │ │ ├── edit_menu.c │ │ ├── edit_menu.h │ │ ├── fill.c │ │ ├── fill.h │ │ ├── graphics.c │ │ ├── graphics.h │ │ ├── macro.c │ │ ├── macro.h │ │ ├── macro_struct.h │ │ ├── pal_ed.c │ │ ├── pal_ed.h │ │ ├── param.c │ │ ├── param.h │ │ ├── robo_debug.c │ │ ├── robo_debug.h │ │ ├── robo_ed.c │ │ ├── robo_ed.h │ │ ├── robot.c │ │ ├── robot.h │ │ ├── select.c │ │ ├── select.h │ │ ├── sfx_edit.c │ │ ├── sfx_edit.h │ │ ├── stringsearch.c │ │ ├── stringsearch.h │ │ ├── undo.c │ │ ├── undo.h │ │ ├── window.c │ │ ├── window.h │ │ ├── world.c │ │ └── world.h │ ├── error.c │ ├── error.h │ ├── event.c │ ├── event.h │ ├── event_sdl.c │ ├── expr.c │ ├── expr.h │ ├── extmem.c │ ├── extmem.h │ ├── game.c │ ├── game.h │ ├── game_menu.c │ ├── game_menu.h │ ├── game_ops.c │ ├── game_ops.h │ ├── game_player.c │ ├── game_player.h │ ├── game_update.c │ ├── game_update.h │ ├── game_update_board.c │ ├── graphics.c │ ├── graphics.h │ ├── hashtable.h │ ├── helpsys.c │ ├── helpsys.h │ ├── idarray.c │ ├── idarray.h │ ├── idput.c │ ├── idput.h │ ├── intake.c │ ├── intake.h │ ├── intake_num.c │ ├── intake_num.h │ ├── io/ │ │ ├── bitstream.h │ │ ├── fsafeopen.c │ │ ├── fsafeopen.h │ │ ├── memfile.h │ │ ├── path.c │ │ ├── path.h │ │ ├── vfile.h │ │ ├── vfs.c │ │ ├── vfs.h │ │ ├── vio.c │ │ ├── vio.h │ │ ├── vio_no_vfs.c │ │ ├── vio_posix.h │ │ ├── vio_volume.h │ │ ├── vio_win32.h │ │ ├── zip.c │ │ ├── zip.h │ │ ├── zip_deflate.h │ │ ├── zip_deflate64.h │ │ ├── zip_dict.h │ │ ├── zip_implode.h │ │ ├── zip_reduce.h │ │ ├── zip_shrink.h │ │ ├── zip_stream.c │ │ └── zip_stream.h │ ├── keysym.h │ ├── legacy_board.c │ ├── legacy_board.h │ ├── legacy_rasm.c │ ├── legacy_rasm.h │ ├── legacy_robot.c │ ├── legacy_robot.h │ ├── legacy_world.c │ ├── legacy_world.h │ ├── main.c │ ├── memcasecmp.h │ ├── mzm.c │ ├── mzm.h │ ├── network/ │ │ ├── DNS.cpp │ │ ├── DNS.hpp │ │ ├── HTTPHost.cpp │ │ ├── HTTPHost.hpp │ │ ├── Host.cpp │ │ ├── Host.hpp │ │ ├── Manifest.cpp │ │ ├── Manifest.hpp │ │ ├── Scoped.hpp │ │ ├── Socket.cpp │ │ ├── Socket.hpp │ │ ├── network.cpp │ │ ├── network.h │ │ ├── server.cpp │ │ ├── sha256.c │ │ └── sha256.h │ ├── nostdc++.cpp │ ├── old/ │ │ ├── legacy_save.c │ │ ├── legacy_save.h │ │ └── render_layer_code.h │ ├── platform.h │ ├── platform_attribute.h │ ├── platform_dummy.c │ ├── platform_endian.h │ ├── platform_sdl.c │ ├── platform_time.c │ ├── pngops.c │ ├── pngops.h │ ├── rasm.c │ ├── rasm.h │ ├── render.c │ ├── render.h │ ├── render_egl.c │ ├── render_egl.h │ ├── render_gl.c │ ├── render_gl.h │ ├── render_gl1.c │ ├── render_gl2.c │ ├── render_glsl.c │ ├── render_gp2x.c │ ├── render_layer.cpp │ ├── render_layer.h │ ├── render_layer_code.hpp │ ├── render_layer_common.hpp │ ├── render_sdl.c │ ├── render_sdl.h │ ├── render_sdlaccel.c │ ├── render_soft.c │ ├── render_softscale.c │ ├── render_yuv.c │ ├── renderers.h │ ├── robot.c │ ├── robot.h │ ├── robot_struct.h │ ├── run_robot.c │ ├── run_stubs.c │ ├── run_stubs.h │ ├── scrdisp.c │ ├── scrdisp.h │ ├── settings.c │ ├── settings.h │ ├── sprite.c │ ├── sprite.h │ ├── sprite_struct.h │ ├── str.c │ ├── str.h │ ├── thread_debug.h │ ├── thread_dummy.h │ ├── thread_pthread.h │ ├── thread_sdl.h │ ├── thread_win32.h │ ├── updater.cpp │ ├── updater.h │ ├── util.c │ ├── util.h │ ├── utils/ │ │ ├── Makefile.in │ │ ├── ccv.c │ │ ├── checkres.c │ │ ├── downver.c │ │ ├── hlp2html.c │ │ ├── hlp2txt.c │ │ ├── image_common.h │ │ ├── image_file.c │ │ ├── image_file.h │ │ ├── image_gif.c │ │ ├── image_gif.h │ │ ├── png2smzx.c │ │ ├── smzxconv.c │ │ ├── smzxconv.h │ │ ├── txt2hlp.c │ │ ├── uthash.h │ │ ├── utils_alloc.h │ │ ├── y4m.c │ │ ├── y4m.h │ │ └── y4m2smzx.c │ ├── window.c │ ├── window.h │ ├── world.c │ ├── world.h │ ├── world_format.h │ ├── world_struct.h │ └── yuv.h ├── testworlds/ │ ├── 1.00/ │ │ ├── 000 Format.mzx │ │ ├── 000 Format.txt │ │ ├── 001 Locked.mzx │ │ ├── 001 Locked.txt │ │ ├── 002 Robo-P Convert.mzx │ │ ├── 002 Robo-P Convert.txt │ │ ├── 003 Char Escapes.mzx │ │ ├── 003 Char Escapes.txt │ │ ├── 004 cur_prog_line.mzx │ │ ├── 004 cur_prog_line.txt │ │ ├── 005 bad cur_prog_line.mzx │ │ ├── 005 bad cur_prog_line.txt │ │ ├── 006 firewalker_dur.mzx │ │ ├── 006 firewalker_dur.txt │ │ ├── 007 wind_dur.mzx │ │ ├── 007 wind_dur.txt │ │ ├── 008 slimeblob.mzx │ │ ├── 008 slimeblob.txt │ │ ├── 009 scan.mzx │ │ ├── 009 scan.txt │ │ ├── 010 rel counters copy.mzx │ │ ├── 010 rel counters copy.txt │ │ ├── 011 Entrances.mzx │ │ ├── 011 Entrances.txt │ │ ├── 012 TELEPORT skip.mzx │ │ ├── 012 TELEPORT skip.txt │ │ ├── 013 Robo-P Color Param.mzx │ │ ├── 013 Robo-P Color Param.txt │ │ ├── 014 Tiger Intel. Movement.mzx │ │ └── 014 Tiger Intel. Movement.txt │ ├── 2.51/ │ │ ├── 000 Swap Test.mzx │ │ ├── 000 Swap Test.txt │ │ ├── 001 Copy No-Restart.mzx │ │ ├── 001 Copy No-Restart.txt │ │ ├── 002 Shoot No-Cycle.mzx │ │ ├── 002 Shoot No-Cycle.txt │ │ ├── 003 Endgame Teleport.mzx │ │ ├── 003 Endgame Teleport.txt │ │ ├── 004 Entrances.mzx │ │ ├── 004 Entrances.txt │ │ ├── 005 COPY player thisx.mzx │ │ ├── 005 COPY player thisx.txt │ │ ├── 006 ZAP RESTORE.mzx │ │ ├── 006 ZAP RESTORE.txt │ │ ├── 007 LOCAL.mzx │ │ ├── 007 LOCAL.txt │ │ ├── 008 Null Boards.mzx │ │ ├── 008 Null Boards.txt │ │ ├── 009 Shark Goop.mzx │ │ ├── 009 Shark Goop.txt │ │ ├── 010 INPUT STRING.MZX │ │ ├── 010 INPUT STRING.txt │ │ ├── 011 Bad Message Row.mzx │ │ ├── 011 Bad Message Row.txt │ │ ├── 012 Custom SFX.mzx │ │ ├── 012 Custom SFX.txt │ │ ├── 013 slimeblob.mzx │ │ ├── 013 slimeblob.txt │ │ ├── 014 scan.mzx │ │ ├── 014 scan.txt │ │ ├── 015 rel counters copy.mzx │ │ ├── 015 rel counters copy.txt │ │ ├── 016 IF ALIGNEDROBOT.mzx │ │ ├── 016 IF ALIGNEDROBOT.txt │ │ ├── 017 TELEPORT noskip.mzx │ │ ├── 017 TELEPORT noskip.txt │ │ ├── 018 Robotic Color Param.mzx │ │ ├── 018 Robotic Color Param.txt │ │ ├── 019 Tiger Intel. Movement.mzx │ │ └── 019 Tiger Intel. Movement.txt │ ├── 2.51s1/ │ │ ├── 001 LOCAL.MZX │ │ └── 001 LOCAL.txt │ ├── 2.60/ │ │ ├── 001 SEND Lock.mzx │ │ ├── 001 SEND Lock.txt │ │ ├── 002 Label Cycle-Ending.mzx │ │ ├── 002 Label Cycle-Ending.txt │ │ ├── 003 Robotic Color Param.mzx │ │ └── 003 Robotic Color Param.txt │ ├── 2.62/ │ │ ├── 001 SET string INPUT.MZX │ │ └── 001 SET string INPUT.txt │ ├── 2.65/ │ │ ├── 001 IF ANY.mzx │ │ ├── 002 GOSTACK.MZX │ │ ├── 003 SPR_NUM.mzx │ │ ├── 003 SPR_NUM.txt │ │ ├── 004 Static Sprite Collision.mzx │ │ ├── 004 Static Sprite Collision.txt │ │ ├── 005 IF ALIGNEDROBOT.mzx │ │ └── 005 IF ALIGNEDROBOT.txt │ ├── 2.69/ │ │ ├── 001 SET &$string&.mzx │ │ └── 002 String in expression.mzx │ ├── 2.69c/ │ │ ├── 001 vlayer.mzx │ │ ├── 002 COPY BLOCK $string.mzx │ │ └── 003 vlayer copy player.mzx │ ├── 2.70/ │ │ ├── 001 BOARD_COLOR No-bleed.mzx │ │ ├── 002 LOAD_ROBOT.mzx │ │ ├── 003 SPR_NUM.mzx │ │ ├── 004 Terminated Str Cmp.mzx │ │ ├── 005 Robotic Color Param.mzx │ │ └── 005 Robotic Color Param.txt │ ├── 2.80/ │ │ ├── 001 IF ANY.mzx │ │ ├── 002 Copy Restart.mzx │ │ ├── 003 Go Stack.mzx │ │ ├── 004 Autodecrypt.mzx │ │ ├── 005 SEND No-Lock.mzx │ │ ├── 006 BOARD_COLOR Bleed.mzx │ │ ├── 007 Endgame Teleport.mzx │ │ ├── 008 set counter str.mzx │ │ ├── 009 FWRITE String.mzx │ │ ├── 010 Robot position.mzx │ │ ├── 011 LOCAL.mzx │ │ ├── 012 BYTE 14.mzx │ │ ├── 013 Robot Stack.mzx │ │ ├── 014 Label Not Cycle-Ending.mzx │ │ ├── 015 INPUT STRING Expr.mzx │ │ ├── 016 IF ALIGNEDROBOT.mzx │ │ ├── 017 Robotic Color Param.mzx │ │ ├── 018 out-of-bounds idput.mzx │ │ ├── 019 Tiger Intel. Movement.mzx │ │ └── d01 Char ID 255.mzx │ ├── 2.81/ │ │ ├── 001 VLAYER_SIZE.mzx │ │ ├── 002 String Splice Assignment.mzx │ │ ├── b00 SAVE_GAME pos.mzx │ │ ├── b01 SAVE_GAME ZAP.mzx │ │ ├── e01 Expressions.mzx │ │ └── e02 Hex Interpolation.mzx │ ├── 2.82/ │ │ └── b01 FWRITE String.mzx │ ├── 2.83/ │ │ └── 001 Shoot Cycle.mzx │ ├── 2.84/ │ │ ├── 001 MZM3 size.mzx │ │ ├── 002 Load 2.84 Save.mzx │ │ ├── 003 COPY prefix.mzx │ │ ├── 004 Arithmetic Rsh.mzx │ │ ├── 005 Builtin Sub.mzx │ │ ├── 006 MZX_SPEED.mzx │ │ ├── 007 Delimiters.mzx │ │ ├── 008 ARCTAN.mzx │ │ ├── 009 set random.mzx │ │ ├── 010 MIN MAX.mzx │ │ ├── 011 LOAD_ROBOT spaces.mzx │ │ ├── b01 Future MZM.mzx │ │ └── c01 global color.mzx │ ├── 2.90/ │ │ ├── 000 Format.mzx │ │ ├── 001 Rearchive.mzx │ │ ├── 002 Data Descriptor.mzx │ │ ├── 003 Go Stack.mzx │ │ ├── 004 GOOP_WALK.mzx │ │ ├── 005 Reset Entry.mzx │ │ ├── 006 Asset Entry.mzx │ │ ├── 007 Sensor Push.mzx │ │ ├── 008 Board ext chars.mzx │ │ ├── 009 MOD_NAME Fail.mzx │ │ ├── 010 SAM-WAV Translate.mzx │ │ ├── 011 LOAD CHAR SET str.mzx │ │ ├── 012 LOAD PALETTE str.mzx │ │ ├── 013 MZM str.mzx │ │ ├── 014 Title Reset Entry.mzx │ │ ├── 015 No Reset same board.mzx │ │ ├── 016 Static Sprite Collision.mzx │ │ ├── 017 Robotic Color Param.mzx │ │ ├── b01 Counter Ineq.mzx │ │ ├── d00 Nested Ternary.mzx │ │ └── d01 Native SAM.mzx │ ├── 2.91/ │ │ ├── 000 Format.mzx │ │ ├── 001 Copy Block Splice.mzx │ │ ├── 002 Wildcards.mzx │ │ ├── 003 ccheck3 clip.mzx │ │ ├── 004 MOD_LENGTH.mzx │ │ ├── 005 String Valid.mzx │ │ ├── 006 String Neg Off.mzx │ │ ├── 007 String Idx Enh.mzx │ │ ├── 008 LOAD_COUNTERS.mzx │ │ ├── 009 Sprite Bounds.mzx │ │ ├── 010 saved vlayer.mzx │ │ ├── 011 remap vlayer.mzx │ │ ├── b00 String Inequlty.mzx │ │ ├── c00 Ternary Expr.mzx │ │ ├── c01 fsafetranslate.mzx │ │ ├── c02 st_load.mzx │ │ ├── c03 slow_down.mzx │ │ ├── e00 Board ext chars.mzx │ │ ├── e01 Str compare.mzx │ │ ├── g00 MZM str length.mzx │ │ ├── g01 SLOW TIME.mzx │ │ └── h00 FWRITEn.mzx │ ├── 2.92/ │ │ ├── 001 FWRITE String.mzx │ │ ├── 002 RAD.mzx │ │ ├── 003 SPR#_OFF read.mzx │ │ ├── 004 Robot position.mzx │ │ ├── 005 FREAD_LENGTH.mzx │ │ ├── 006 MOD_LOOPSTART.mzx │ │ ├── 007 SAVE_ROBOTn str.mzx │ │ ├── 008 SPR_NUM.mzx │ │ ├── 100 IF &$string&.mzx │ │ ├── c01 Ternary idents.mzx │ │ ├── c02 BYTE 14.mzx │ │ ├── d01 fsafetranslate SFN.mzx │ │ ├── d02 SMZX ccheck3.mzx │ │ ├── g01 LOAD CHAR SET crash.mzx │ │ ├── g02 String MZM Size.mzx │ │ ├── g03 Reset Missing Temp.mzx │ │ ├── g04 set random range.mzx │ │ ├── g05 divide INT_MIN -1.mzx │ │ ├── g06 Bad Current Board.290.mzx │ │ ├── g07 Bad Current Board.284.mzx │ │ ├── g08 Bad Board IDs.mzx │ │ ├── g09 Bad Saved Pos.290.mzx │ │ ├── g10 Bad Saved Pos.284.mzx │ │ ├── g11 Bad cur_prog_line.290.mzx │ │ ├── g12 Bad cur_prog_line.284.mzx │ │ ├── g13 Bad stack pointer.290.mzx │ │ ├── g14 Bad stack pointer.284.mzx │ │ ├── g15 Bad stack size.284.mzx │ │ ├── g16 Bad Message Row.mzx │ │ ├── g17 Bad stack frame.290.mzx │ │ ├── g18 Bad stack frame.284.mzx │ │ ├── g19 Invalid Robotic Item.mzx │ │ └── g20 Invalid Condition.mzx │ ├── 2.93/ │ │ ├── 000 Format.mzx │ │ ├── 001 Custom SFX.mzx │ │ ├── 002 Custom SFX (old).mzx │ │ ├── 003 FWRITE Mode Save Test.mzx │ │ ├── 004 MZX Pal in SMZX Mode.mzx │ │ ├── 005 Viewport Counters.mzx │ │ ├── 006 DATE_WEEKDAY.mzx │ │ ├── 007 playerdied.mzx │ │ ├── 008 Dragon Random.mzx │ │ ├── 009 Reset same board off.mzx │ │ ├── 010 Reset same board on.mzx │ │ ├── 011 SPRn_OFFONEXIT.mzx │ │ ├── 012 Static Sprite Collision.mzx │ │ ├── b01 String Splice Assignment.mzx │ │ ├── b02 String Splice FREAD Crash.mzx │ │ ├── b03 IF ALIGNEDROBOT.mzx │ │ ├── c01 CHANGE OVERLAY immediate.mzx │ │ └── e01 DOS chars devices.mzx │ ├── 2.XX/ │ │ └── 000 MOD Formats.mzx │ ├── README.md │ ├── data/ │ │ ├── LOCKED.MZX │ │ ├── README.md │ │ ├── audio/ │ │ │ ├── 1s.ogg │ │ │ ├── 1s_badtag.ogg │ │ │ ├── CRYSTALS.WOW │ │ │ ├── CV_BOSS.MOD │ │ │ ├── GBUSTERS.MOD │ │ │ ├── PAIN.SAM │ │ │ ├── SX-shrine.it │ │ │ ├── Shayde - Canon in D.rad │ │ │ ├── Void - Dystopia.rad │ │ │ ├── XON_BATT.AMF │ │ │ ├── analog.ult │ │ │ ├── basket.s3m │ │ │ ├── bit_loader.xm │ │ │ ├── black_box.okt │ │ │ ├── bluesy.mod │ │ │ ├── chip_happy.med │ │ │ ├── crystals.669 │ │ │ ├── desecret.mod │ │ │ ├── drivin.gdm │ │ │ ├── ekorren.mod │ │ │ ├── fiercest.amf │ │ │ ├── georythm.stm │ │ │ ├── gidion graveland.mod │ │ │ ├── jul-paaske.mod │ │ │ ├── mindflux.rad │ │ │ ├── misimprm.mod │ │ │ ├── moods-yeah.med │ │ │ ├── new age.mod │ │ │ ├── no_tears.med │ │ │ ├── popcorn.dsm │ │ │ ├── ref 8.mod │ │ │ ├── rip4.rad │ │ │ ├── s0d.mod │ │ │ ├── soap bubble.mod │ │ │ ├── something's amiss.mtm │ │ │ ├── the rain in the ruin.far │ │ │ ├── wizardry.med │ │ │ └── xxy_cursor.ogg │ │ ├── bad_cur_prog_line.284.sav │ │ ├── bad_cur_prog_line.290.sav │ │ ├── bad_current_board.284.sav │ │ ├── bad_current_board.290.sav │ │ ├── bad_saved_pos_board.284.sav │ │ ├── bad_saved_pos_board.290.sav │ │ ├── bad_stack_frame.284.sav │ │ ├── bad_stack_frame.290.sav │ │ ├── bad_stack_pointer.284.sav │ │ ├── bad_stack_pointer.290.sav │ │ ├── bad_stack_size.284.sav │ │ ├── futer.mzm │ │ ├── loadassetentryA.chr │ │ ├── loadassetentryA.pal │ │ ├── loadassetentryB.chr │ │ ├── loadassetentryB.pal │ │ ├── reset_entry_no_temp.sav │ │ ├── saved.284c.sav │ │ └── spaces.txt │ ├── run.sh │ └── temp/ │ └── README.md ├── unit/ │ ├── Makefile.in │ ├── Unit.cpp │ ├── Unit.hpp │ ├── UnitIO.cpp │ ├── UnitIO.hpp │ ├── align.cpp │ ├── audio/ │ │ ├── mixer/ │ │ │ ├── CUBIC_mm.raw │ │ │ ├── CUBIC_mm_dyn.raw │ │ │ ├── CUBIC_ms.raw │ │ │ ├── CUBIC_ms_dyn.raw │ │ │ ├── CUBIC_sm.raw │ │ │ ├── CUBIC_sm_dyn.raw │ │ │ ├── CUBIC_ss.raw │ │ │ ├── CUBIC_ss_dyn.raw │ │ │ ├── FLAT_mm.raw │ │ │ ├── FLAT_mm_dyn.raw │ │ │ ├── FLAT_ms.raw │ │ │ ├── FLAT_ms_dyn.raw │ │ │ ├── FLAT_sm.raw │ │ │ ├── FLAT_sm_dyn.raw │ │ │ ├── FLAT_ss.raw │ │ │ ├── FLAT_ss_dyn.raw │ │ │ ├── LINEAR_mm.raw │ │ │ ├── LINEAR_mm_dyn.raw │ │ │ ├── LINEAR_ms.raw │ │ │ ├── LINEAR_ms_dyn.raw │ │ │ ├── LINEAR_sm.raw │ │ │ ├── LINEAR_sm_dyn.raw │ │ │ ├── LINEAR_ss.raw │ │ │ ├── LINEAR_ss_dyn.raw │ │ │ ├── NEAREST_mm.raw │ │ │ ├── NEAREST_mm_dyn.raw │ │ │ ├── NEAREST_ms.raw │ │ │ ├── NEAREST_ms_dyn.raw │ │ │ ├── NEAREST_sm.raw │ │ │ ├── NEAREST_sm_dyn.raw │ │ │ ├── NEAREST_ss.raw │ │ │ ├── NEAREST_ss_dyn.raw │ │ │ ├── m.raw │ │ │ └── s.raw │ │ └── mixer.cpp │ ├── configure.cpp │ ├── editor/ │ │ └── stringsearch.cpp │ ├── expr.cpp │ ├── intake.cpp │ ├── io/ │ │ ├── bitstream.cpp │ │ ├── data/ │ │ │ ├── CN_S.CHR │ │ │ ├── CN_S.CHR.deflate │ │ │ ├── CN_S.CHR.implode │ │ │ ├── CN_S.CHR.reduce1 │ │ │ ├── CN_S.CHR.reduce2 │ │ │ ├── CN_S.CHR.reduce3 │ │ │ ├── CN_S.CHR.reduce4 │ │ │ ├── CN_S.CHR.shrink │ │ │ ├── CT_LEVEL.MOD │ │ │ ├── FREAKSOF.MZX │ │ │ ├── ct_level.deflate │ │ │ ├── ct_level.deflate64 │ │ │ ├── ct_level.implode │ │ │ ├── ct_level.reduce1 │ │ │ ├── ct_level.reduce2 │ │ │ ├── ct_level.reduce3 │ │ │ ├── ct_level.reduce4 │ │ │ ├── ct_level.shrink │ │ │ ├── dch1.deflate │ │ │ ├── dch1.deflate64 │ │ │ ├── dch1.implode │ │ │ ├── dch1.reduce1 │ │ │ ├── dch1.reduce2 │ │ │ ├── dch1.reduce3 │ │ │ ├── dch1.reduce4 │ │ │ ├── dch1.shrink │ │ │ ├── dch1.txt │ │ │ ├── dch1.zip64 │ │ │ ├── freaksof.deflate │ │ │ ├── freaksof.deflate64 │ │ │ ├── freaksof.implode │ │ │ ├── freaksof.reduce1 │ │ │ ├── freaksof.reduce2 │ │ │ ├── freaksof.reduce3 │ │ │ ├── freaksof.reduce4 │ │ │ ├── freaksof.shrink │ │ │ └── zip64/ │ │ │ └── zip64gen.cpp │ │ ├── memfile.cpp │ │ ├── path.cpp │ │ ├── vfs.cpp │ │ ├── vio.cpp │ │ └── zip.cpp │ ├── memcasecmp.cpp │ ├── network/ │ │ ├── Manifest.cpp │ │ ├── data/ │ │ │ ├── 1.txt │ │ │ ├── 2.txt │ │ │ └── manifest.txt │ │ └── sha256.cpp │ ├── render.cpp │ ├── sfx.cpp │ ├── thread.cpp │ ├── thread.hpp │ ├── thread_win32.cpp │ ├── utils/ │ │ ├── image_file/ │ │ │ ├── farbfeld.ff │ │ │ ├── p1.pbm │ │ │ ├── p2.pgm │ │ │ ├── p2_18.pgm │ │ │ ├── p2_64.pgm │ │ │ ├── p3.ppm │ │ │ ├── p3_18.ppm │ │ │ ├── p3_64.ppm │ │ │ ├── p4.pbm │ │ │ ├── p5.pgm │ │ │ ├── p5_18.pgm │ │ │ ├── p5_64.pgm │ │ │ ├── p6.ppm │ │ │ ├── p6_18.ppm │ │ │ ├── p6_64.ppm │ │ │ ├── p7_gs.pam │ │ │ ├── p7_gs18.pam │ │ │ ├── p7_gs64.pam │ │ │ ├── p7_gsa.pam │ │ │ ├── p7_gsa18.pam │ │ │ ├── p7_gsa64.pam │ │ │ ├── p7_rgb.pam │ │ │ ├── p7_rgb18.pam │ │ │ ├── p7_rgb64.pam │ │ │ ├── p7_rgba.pam │ │ │ ├── p7_rgba18.pam │ │ │ ├── p7_rgba64.pam │ │ │ ├── raw_gs.raw │ │ │ ├── raw_gsa.raw │ │ │ ├── raw_rgb.raw │ │ │ ├── raw_rgba.raw │ │ │ ├── tga_15bpp.tga │ │ │ ├── tga_16bpp.tga │ │ │ ├── tga_16bpp_rle.tga │ │ │ ├── tga_16bpp_ttb.tga │ │ │ ├── tga_16bpp_ttb_rle.tga │ │ │ ├── tga_24bpp.tga │ │ │ ├── tga_24bpp_rle.tga │ │ │ ├── tga_24bpp_ttb.tga │ │ │ ├── tga_24bpp_ttb_rle.tga │ │ │ ├── tga_32bpp.tga │ │ │ ├── tga_32bpp_rle.tga │ │ │ ├── tga_32bpp_rtl.tga │ │ │ ├── tga_32bpp_rtl_ttb.tga │ │ │ ├── tga_32bpp_ttb.tga │ │ │ ├── tga_32bpp_ttb_rle.tga │ │ │ ├── tga_g.tga │ │ │ ├── tga_g_rle.tga │ │ │ ├── tga_g_ttb.tga │ │ │ ├── tga_g_ttb_rle.tga │ │ │ ├── tga_idx16_32bpp.tga │ │ │ ├── tga_idx16_32bpp_rle.tga │ │ │ ├── tga_idx16_32bpp_ttb.tga │ │ │ ├── tga_idx16_32bpp_ttb_rle.tga │ │ │ ├── tga_idx8_15bpp.tga │ │ │ ├── tga_idx8_16bpp.tga │ │ │ ├── tga_idx8_16bpp_rle.tga │ │ │ ├── tga_idx8_16bpp_ttb.tga │ │ │ ├── tga_idx8_16bpp_ttb_rle.tga │ │ │ ├── tga_idx8_24bpp.tga │ │ │ ├── tga_idx8_24bpp_rle.tga │ │ │ ├── tga_idx8_24bpp_ttb.tga │ │ │ ├── tga_idx8_24bpp_ttb_rle.tga │ │ │ ├── tga_idx8_32bpp.tga │ │ │ ├── tga_idx8_32bpp_rle.tga │ │ │ ├── tga_idx8_32bpp_ttb.tga │ │ │ └── tga_idx8_32bpp_ttb_rle.tga │ │ └── image_file.cpp │ └── world.cpp ├── valgrind.supp └── version.inc ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ .gitignore merge=union text docs/changelog.txt merge=union text docs/cycles_and_commands.txt text docs/idle_direction_oddities.txt text docs/macro.txt text docs/port.txt text docs/push_and_transport.txt text docs/WIPHelp.txt text unit/io/data/*.txt text eol=lf config.txt text ================================================ FILE: .github/workflows/main.yml ================================================ name: Regression tests env: MZXDEPS_DEBIAN_SDL2: "zlib1g-dev libpng-dev libogg-dev libvorbis-dev libsdl2-dev" MZXDEPS_DEBIAN_MISC: "libsdl1.2-dev libegl1-mesa-dev libmikmod-dev libopenmpt-dev" MZXDEPS_MACOS: "libpng libogg libvorbis sdl2" MZX_MAKE: "make -j4" on: push: branches: [ master ] pull_request: branches: [ master ] workflow_dispatch: jobs: # # Platform variants and distribution packages. # unix: runs-on: ubuntu-latest steps: - name: Install dependencies run: sudo apt update && sudo apt install -y --no-install-recommends $MZXDEPS_DEBIAN_SDL2 - uses: actions/checkout@v4 - name: Configure run: ./config.sh --platform unix --enable-release --enable-sdlaccel - name: Build run: $MZX_MAKE - name: Run tests run: $MZX_MAKE test - name: Install run: sudo $MZX_MAKE install V=1 - name: Check install run: command -v megazeux && [ -f "/usr/share/licenses/megazeux/LICENSE" ] && [ -f "/etc/megazeux-config" ] - name: Uninstall run: sudo $MZX_MAKE uninstall V=1 - name: Check uninstall run: true && [ ! -f "/usr/bin/megazeux" ] && [ ! -f "/usr/share/licenses/megazeux/LICENSE" ] && [ ! -f "/etc/megazeux-config" ] - name: Package source .tar.xz run: make source unix-portable: runs-on: ubuntu-latest steps: - name: Install dependencies run: sudo apt update && sudo apt install -y --no-install-recommends $MZXDEPS_DEBIAN_SDL2 - uses: actions/checkout@v4 - name: Configure run: ./config.sh --platform unix-devel --enable-release --enable-sdlaccel - name: Build run: $MZX_MAKE - name: Run tests run: $MZX_MAKE test - name: Package linux-amd64 .zip run: make archive unix-misc: runs-on: ubuntu-latest steps: - name: Install dependencies run: sudo apt update && sudo apt install -y --no-install-recommends $MZXDEPS_DEBIAN_SDL2 $MZXDEPS_DEBIAN_MISC - uses: actions/checkout@v4 - name: Configure (SDL 1.2) run: ./config.sh --platform unix-devel --enable-release --enable-sdl1 - name: Build (SDL 1.2) run: $MZX_MAKE - name: Run tests (SDL 1.2) run: $MZX_MAKE test - name: Distclean (SDL 1.2) run: $MZX_MAKE distclean - name: Configure (EGL/X11) run: ./config.sh --platform unix-devel --enable-release --disable-sdl --enable-egl - name: Build (EGL/X11) run: $MZX_MAKE # Note: EGL mzxrun builds can't run headless, unit tests only. - name: Run tests (EGL/X11) run: $MZX_MAKE unit - name: Distclean (EGL/X11) run: $MZX_MAKE distclean - name: Configure (ModPlug) run: ./config.sh --platform unix-devel --enable-release --enable-modplug - name: Build (Modplug) run: $MZX_MAKE - name: Run tests (Modplug) run: $MZX_MAKE test - name: Distclean (Modplug) run: $MZX_MAKE distclean - name: Configure (MikMod) run: ./config.sh --platform unix-devel --enable-release --enable-mikmod - name: Build (MikMod) run: $MZX_MAKE - name: Run tests (MikMod) run: $MZX_MAKE test - name: Distclean (MikMod) run: $MZX_MAKE distclean - name: Configure (OpenMPT) run: ./config.sh --platform unix-devel --enable-release --enable-openmpt - name: Build (OpenMPT) run: $MZX_MAKE - name: Run tests (OpenMPT) run: $MZX_MAKE test - name: Distclean (OpenMPT) run: $MZX_MAKE distclean - name: Configure (debug) run: ./config.sh --platform unix-devel --disable-release --enable-trace --enable-fps - name: Build (debug) run: $MZX_MAKE - name: Run tests (debug) run: $MZX_MAKE test - name: Distclean (debug) run: $MZX_MAKE distclean darwin-arm64: runs-on: macos-latest steps: - uses: actions/checkout@v4 - name: Install dependencies run: brew install $MZXDEPS_MACOS - name: Configure (darwin-devel) run: ./config.sh --platform darwin-devel --prefix /opt/homebrew --enable-release --enable-sdlaccel - name: Build (darwin-devel) run: $MZX_MAKE - name: Run tests (darwin-devel) run: $MZX_MAKE test darwin-x86_64: runs-on: macos-26-intel steps: - uses: actions/checkout@v4 - name: Install dependencies run: brew install $MZXDEPS_MACOS - name: Configure (darwin-devel) run: ./config.sh --platform darwin-devel --prefix /usr/local --enable-release --enable-sdlaccel - name: Build (darwin-devel) run: $MZX_MAKE - name: Run tests (darwin-devel) run: $MZX_MAKE test MSYS2-MINGW64: runs-on: windows-latest defaults: run: shell: msys2 {0} steps: - name: Setup msys2 uses: msys2/setup-msys2@v2 with: msystem: MINGW64 update: true install: >- base-devel git zip mingw-w64-x86_64-gcc mingw-w64-x86_64-zlib mingw-w64-x86_64-libpng mingw-w64-x86_64-libogg mingw-w64-x86_64-libvorbis mingw-w64-x86_64-SDL2 - uses: actions/checkout@v4 - name: Configure x64 run: ./config.sh --platform win64 --enable-release - name: Build x64 run: $MZX_MAKE - name: Test x64 run: $MZX_MAKE test - name: Package x64 .zip run: make archive MSYS2-MINGW32: runs-on: windows-latest defaults: run: shell: msys2 {0} steps: - name: Setup msys2 uses: msys2/setup-msys2@v2 with: msystem: MINGW32 update: true install: >- base-devel git zip mingw-w64-i686-gcc mingw-w64-i686-zlib mingw-w64-i686-libpng mingw-w64-i686-libogg mingw-w64-i686-libvorbis mingw-w64-i686-SDL2 - uses: actions/checkout@v4 - name: Configure x86 run: ./config.sh --platform win32 --enable-release - name: Build x86 run: $MZX_MAKE - name: Test x86 run: $MZX_MAKE test - name: Package x86 .zip run: make archive AArch64-Switch: runs-on: ubuntu-latest container: devkitpro/devkita64 steps: - run: echo "PATH=$DEVKITPRO/devkitA64/bin:$PATH" >> $GITHUB_ENV - uses: actions/checkout@v4 - name: Configure Switch run: arch/switch/CONFIG.SWITCH - name: Build Switch run: $MZX_MAKE - name: Package Switch .zip run: make archive ARM-3DS: runs-on: ubuntu-latest container: devkitpro/devkitarm steps: - run: echo "PATH=$DEVKITPRO/devkitARM/bin:$PATH" >> $GITHUB_ENV - uses: actions/checkout@v4 - name: Configure 3DS run: arch/3ds/CONFIG.3DS - name: Build 3DS run: $MZX_MAKE - name: Package 3DS .zip run: make archive ARM-NDS: runs-on: ubuntu-latest container: devkitpro/devkitarm:20241104 steps: - run: echo "PATH=$DEVKITPRO/devkitARM/bin:$PATH" >> $GITHUB_ENV - uses: actions/checkout@v4 - name: Configure NDS run: arch/nds/CONFIG.NDS - name: Build NDS run: $MZX_MAKE - name: Package NDS .zip run: make archive ARM-NDS-BlocksDS: runs-on: ubuntu-latest container: skylyrac/blocksds:slim-latest steps: - name: Install dependencies run: apt update && apt install -y --no-install-recommends zip - name: Install target dependencies run: wf-pacman -S --noconfirm toolchain-gcc-arm-none-eabi-zlib - uses: actions/checkout@v4 - name: Configure NDS/BlocksDS run: arch/nds-blocksds/CONFIG.NDS - name: Build NDS/BlocksDS run: $MZX_MAKE - name: Package NDS/BlocksDS .zip run: make archive PowerPC-Wii: runs-on: ubuntu-latest container: devkitpro/devkitppc steps: - run: echo "PATH=$DEVKITPRO/devkitPPC/bin:$PATH" >> $GITHUB_ENV - uses: actions/checkout@v4 - name: Configure Wii run: arch/wii/CONFIG.WII - name: Build Wii run: $MZX_MAKE - name: Package Wii .zip run: make archive PowerPC-WiiU: runs-on: ubuntu-latest container: devkitpro/devkitppc steps: - run: echo "PATH=$DEVKITPRO/devkitPPC/bin:$PATH" >> $GITHUB_ENV - uses: actions/checkout@v4 - name: Configure Wii U run: arch/wiiu/CONFIG.WIIU - name: Build Wii U run: $MZX_MAKE - name: Package Wii U .zip run: make archive Emscripten-HTML5: runs-on: ubuntu-latest steps: - name: Install Emscripten uses: mymindstorm/setup-emsdk@v14 with: version: 4.0.7 # actions-cache-folder: 'emsdk-cache' - uses: actions/checkout@v4 - name: Configure HTML5 run: arch/emscripten/CONFIG.HTML5 - name: Build HTML5 run: $MZX_MAKE && make build - name: Package HTML5 .zip run: make archive # FIXME: vitasdk hasn't bothered adding SDL3 to the container, # vdpm and git are missing from the container. Vita: runs-on: ubuntu-latest container: vitasdk/vitasdk steps: - name: Install dependencies run: apk add --no-cache zip - uses: actions/checkout@v4 - name: Configure Vita run: arch/psvita/CONFIG.PSVITA --enable-sdl2 --disable-libpng --disable-lto - name: Build Vita run: $MZX_MAKE - name: Package Vita run: make archive # # Sanitizers. # AddressSanitizer: runs-on: ubuntu-latest env: CC: clang CXX: clang++ steps: - name: Install dependencies run: sudo apt update && sudo apt install -y --no-install-recommends $MZXDEPS_DEBIAN_SDL2 - uses: actions/checkout@v4 - name: Configure run: ./config.sh --platform unix-devel --enable-asan --enable-extram - name: Build run: $MZX_MAKE - name: Run tests run: $MZX_MAKE test # Note: requires all non-system/libc calls to be from instrumented libraries. # For the regression tests, MZX can get away with just zlib. # SDL calls into uninstrumented functions and is not built at all. # libpng is temporarily disabled. libogg/libvorbis work with no issue. MemorySanitizer: runs-on: ubuntu-latest env: CC: clang CXX: clang++ steps: - uses: actions/checkout@v4 - name: Fetch dependencies run: | (cd scripts/deps; wget https://github.com/AliceLR/megazeux-dependencies/releases/download/v2.93c-r1/megazeux-dependencies-2.93c-r1-linux-msan-mint22.tar.xz; tar -xJf megazeux-dependencies-*-linux-msan-mint22.tar.xz) - name: Configure run: ./config.sh --platform unix-devel --prefix scripts/deps/linux-msan/x86_64 --enable-msan --disable-sdl --disable-libpng --disable-x11 --enable-extram - name: Build run: $MZX_MAKE V=1 - name: Run tests run: $MZX_MAKE V=1 test UndefinedBehaviorSanitizer: runs-on: ubuntu-latest env: CC: clang CXX: clang++ UBSAN_OPTIONS: print_stacktrace=1 steps: - name: Install dependencies run: sudo apt update && sudo apt install -y --no-install-recommends $MZXDEPS_DEBIAN_SDL2 - uses: actions/checkout@v4 - name: Configure run: ./config.sh --platform unix-devel --enable-ubsan --enable-extram - name: Build run: $MZX_MAKE - name: Run tests run: $MZX_MAKE test ================================================ FILE: .gitignore ================================================ arch/3ds/*.d arch/3ds/*.o arch/3ds/*shbin* arch/android/deps arch/android/include arch/android/project/.eclipse arch/android/project/.gradle arch/android/project/.idea arch/android/project/*.iml arch/android/project/*.ipr arch/android/project/app/.cxx arch/android/project/app/.externalNativeBuild arch/android/project/app/jni/.gradle arch/android/project/app/jni/SDL2 arch/android/project/app/jni/lib arch/android/project/app/jni/libogg arch/android/project/app/jni/libvorbis arch/android/project/app/debug/ arch/android/project/app/release/ arch/android/project/app/src/main/res/raw/assets.zip arch/android/project/app/*.iml arch/android/project/build arch/android/project/keystore.properties arch/android/project/local.properties arch/djgpp/*.d arch/djgpp/*.o arch/dreamcast/*.d arch/dreamcast/*.o arch/emscripten/web/mzxrun_web.js* arch/emscripten/web/node_modules arch/emscripten/web/package-lock.json arch/mingw/pefix arch/mingw/pefix.d arch/mingw/pefix.exe arch/mingw/pefix.o arch/msvc/.vs arch/msvc/*.user arch/msvc/Deps/ arch/msvc/MegaZeux.opensdf arch/msvc/MegaZeux.sdf arch/msvc/MegaZeux.v12.suo arch/msvc/obj arch/msvc/version.h arch/nds/mzxrun.arm7.elf arch/nds/protected_palette_bin.c arch/nds/protected_palette_bin.h arch/nds/*.S arch/nds/*.d arch/nds/*.o arch/psp/*.d arch/psp/*.o arch/psvita/*.d arch/psvita/*.o arch/wii/*.d arch/wii/*.o arch/xcode/version.h build contrib/gdm2s3m/src/.build/ contrib/icons/.build/ contrib/libmodplug/src/.build/ contrib/libxmp/src/.build/ contrib/libxmp/src/win32/.build/ contrib/libxmp/src/loaders/.build/ contrib/unzip/src/.build/ 1ST_READ.BIN boot.dol Core.exp Core.ilk Core.iobj Core.ipdb Core.lib Core.pdb core.dll libcore.so libcore.dylib EBOOT.PBP eboot.bin Editor.exp Editor.ilk Editor.iobj Editor.ipdb Editor.lib Editor.map Editor.pdb editor.dll ICON0.PNG libeditor.so libeditor.dylib megazeux-cia.* megazeux.3dsx megazeux.bin megazeux.dol megazeux.elf megazeux.exe megazeux.exp MegaZeux.ilk MegaZeux.iobj MegaZeux.ipdb MegaZeux.lib megazeux.nacp megazeux.nro megazeux.nso MegaZeux.pdb megazeux.rpx megazeux.smdh megazeux.velf megazeux.vpk /megazeux mzxrun.3dsx mzxrun.bin mzxrun.cia mzxrun.dol mzxrun.elf mzxrun.exe mzxrun.exp mzxrun.ilk mzxrun.iobj mzxrun.ipdb mzxrun.js mzxrun.js.orig.js mzxrun.js.mem mzxrun.lib mzxrun.nacp mzxrun.nds mzxrun.nro mzxrun.nso mzxrun.pdb mzxrun.rpx mzxrun.smdh mzxrun.velf mzxrun.vpk mzxrun.wasm mzxrun.wasm.map /mzxrun PARAM.SFO param.sfo platform.inc SDL.dll SDL2.dll src/.build/ src/config.h src/audio/.build/ src/editor/.build/ src/io/.build/ src/network/.build/ src/utils/.build/ src/utils/ccv.exe src/utils/ccv src/utils/checkres.exe src/utils/checkres src/utils/downver.exe src/utils/downver src/utils/hlp2html.exe src/utils/hlp2html src/utils/hlp2txt.exe src/utils/hlp2txt src/utils/txt2hlp.exe src/utils/txt2hlp src/utils/png2smzx.exe src/utils/png2smzx src/utils/y4m2smzx.exe src/utils/y4m2smzx src/utils/*.debug stdout.txt stderr.txt Thumbs.db unit/.build/ unit/audio/.build/ unit/editor/.build/ unit/io/.build/ unit/network/.build/ unit/utils/.build/ /*.js /*.js.mem /*.js.orig.js /*.wasm /*.wasm.map *.code-workspace *.debug *.mzx *.sav *.mzm *~ .clangd .vscode .DS_Store xcuserdata/ # This MUST go after the *.mzx rule. !testworlds/*/*.mzx testworlds/*/backup* testworlds/backup* testworlds/log testworlds/next testworlds/test testworlds/temp/* !testworlds/temp/README.md !testworlds/data/* ================================================ FILE: .valgrindrc ================================================ --memcheck:leak-check=full --memcheck:track-origins=yes --suppressions=valgrind.supp ================================================ FILE: BUILDING.md ================================================ Building MegaZeux ================= MegaZeux can currently be built for Microsoft Windows, Linux, macOS, NetBSD, FreeBSD, OpenBSD, Haiku, Amiga OS 4, Android, HTML5, MS-DOS (DJGPP), NDS, 3DS, Wii, Wii U, Switch, PSP, Vita, Dreamcast, GP2X, and Pandora. MegaZeux has three buildsystems--the GNU Make buildsystem for building most ports, the Xcode project (`arch/xcode/`) for development and release builds on macOS, and the MSVC project (`arch/msvc/`) for testing on Windows. This document applies primarily to the GNU Make buildsystem. For architecture specific build instructions, please see `arch/[platform]/README`. [The DigitalMZX wiki](https://www.digitalmzx.com/wiki/Compiling_MegaZeux) has more info, particularly for setting up console toolchains. Requirements ------------ For the GNU Make buildsystem, most versions of these tools from the past 20 years work with little issue. You should almost always use the most recent versions available. - POSIX-compatible base system e.g. Linux, macOS, BSD, MSYS2: - **GNU coreutils**: <=4.5.3 or newer (packaging MinGW requires `sha256sum`, 6.0+) - **BusyBox**: <=1.22 or newer (packaging MinGW requires `sha256sum`, 1.14.0+) - (**BSD** `sha256` or **Perl** `shasum -a256` also works.) - GNU-compatible C and C++ compilers: - **GCC**: 3.4 or newer - **clang/LLVM** - **GNU binutils** or **LLVM** or equivalent - **GNU Make**: <=3.79 or newer - **pkgconf** or **pkg-config** (SDL 3 builds only) - **zip** or **7za** (packaging only) - **tar** and **xz** (packaging source only) - **ImageMagick** 7.0 or newer (rebuilding icons only) - Older versions may work if `MAGICK=convert` is provided to Make. - **GraphicsMagick** does not work as a substitute (no parentheses or clone). Dependencies: - **SDL** (all ports except DJGPP, NDS, 3DS, Wii, and Dreamcast) [(link)](https://www.libsdl.org/) - **SDL 3** (with `--enable-sdl3`) - **SDL 2** (default) - **SDL 1.2**: <=1.2.5 or newer (with `--enable-sdl1`) - Clipboard support for SDL 1.2 in Linux additionally requires X11 headers. - **zlib**: 1.2.0 or newer [(link)](https://www.zlib.net/) - **libpng**: 1.2.3 or newer (or `--disable-libpng`) [(link)](http://www.libpng.org/pub/png/libpng.html) - **libogg**: 1.0 or newer (or **stb_vorbis** or `--disable-vorbis`) [(link)](https://xiph.org/downloads/) - **libvorbis**: 1.2.2 or newer (or **Tremor** or **stb_vorbis** or `--disable-vorbis`) [(link)](https://xiph.org/downloads/) For MinGW, DJGPP, and Darwin (macOS/Mac OS X), plus the Xcode and MSVC projects, prebuilt dependencies can be found [here](https://github.com/AliceLR/megazeux-dependencies). See below or the platform-specific README for more info. Configuring and building ------------------------ All operations must be run within a POSIX-compatible shell environment such as Bash, BusyBox, ksh, MSYS2 terminal, or similar. Configure MegaZeux with the script `config.sh` located in the source root: ```sh # You may need to specify --prefix [dir] or other options. # For debug builds, omit --enable-release and --enable-lto. ./config.sh --platform [platform] --enable-release --enable-lto # For a full list of supported options and platforms: ./config.sh ``` Several platforms have shell scripts named `CONFIG.[arch]` located in their `arch/[platform]/` directory, which will run `config.sh` with appropriate default configurations. Compile MegaZeux with GNU Make: ```sh # Use gmake on NetBSD et al. # For verbose output, provide V=1. Parallel builds (-j#) are supported. make # For some platforms, it's safe to override the compilers if needed. # (Most platforms that prefer clang will automatically select it.) CC=clang CXX=clang++ make ``` MegaZeux comes with two regression test systems to verify that MegaZeux works (for platforms and build environments where executables can be run locally). The unit tests located in `unit/` are compiled and executed individually. The test worlds located in `testworlds/` are run together via MZXRun. ```sh # Perform the unit tests and then run the test worlds. (-j# supported) make test # Perform just the unit tests. (-j# supported) make unit # Perform just the test worlds. make testworlds ``` Installing ---------- For Linux/BSD/etc. using the `unix` platform and macOS/Mac OS X using the `darwin` platform, MegaZeux can be installed to the install root that was provided to the `--prefix` option. (Note the default install root is `/usr`, so you may want to explicitly change that to `/usr/local` or similar): ```sh # As superuser: make install # Can be reversed: make uninstall ``` Packaging --------- For all other platforms, MegaZeux is typically packaged instead. MegaZeux's packaging varies from platform to platform. First, for platforms that don't automatically separate or strip debug info (mainly MinGW and DJGPP), separate the debug info. (For MinGW, this also runs the locally compiled tool `arch/mingw/pefix` to strip PE timestamps.) ```sh make debuglink -j8 ``` Package the MegaZeux build into a zip archive. The prepared build directory can be found at `build/[platform]/` and the archive at `build/dist/[platform]/`: ```sh make archive ``` To prepare a directory (in `build/[platform]/`) for packaging without archiving it, this can usually be used instead: ```sh make build ``` To package a source tarball from a local Git repository: ```sh make source ``` Platform-specific notes ----------------------- Check `arch/[platform]/README[.md]` for more detailed platform-specific information. ### Debian-based distributions .deb packages can be generated with a single command. See `debian/README` for more information. ### RPM-based distributions .rpm packages can be generated with a single command: ```sh rpmbuild -bb --build-in-place megazeux.spec ``` ### Other Linux/BSD Use platform `unix` for `make install` or `unix-devel` for running directly from the source directory. ### MinGW and DJGPP Download the latest dependencies tarball from [here](https://github.com/AliceLR/megazeux-dependencies) and extract it into `scripts/deps/`. Provide the following to `config.sh`: - MINGW64: `--platform win64 --prefix scripts/deps/mingw/x64` - MINGW32: `--platform win32 --prefix scripts/deps/mingw/x86` - DJGPP: set `DJGPP` environment variable to `scripts/deps/djgpp/i386` and run `arch/djgpp/CONFIG.DJGPP` from the base directory. When cross-compiling from Linux, use platforms `mingw64` and `mingw32` instead. Additionally, DJGPP currently requires a copy of CWSDPMI.EXE to be placed in `arch/djgpp/` for packaging. ### Darwin (macOS/Mac OS X via GNU Make) Use platform `darwin` for `make install`, `darwin-devel` for running from the source directory, and `darwin-dist` to build a portable multi-architecture .app for distribution (see `arch/darwin/README.md` for more info on `darwin-dist`). All three variants require Xcode to be installed with available command line tools. It is easiest to get the dependency libraries from MacPorts (prefix `/opt/local`) or from the MegaZeux prebuilt dependencies. For `darwin-dist` (and optionally `darwin-devel`), download the latest dependencies tarball from [here](https://github.com/AliceLR/megazeux-dependencies) and extract it into `scripts/deps/`. In addition to the requirements listed in the general requirements section, `darwin-dist` also requires dylibbundler, which (along with other tools) is easiest to get via MacPorts. ### Other notes Amiga OS 4, GP2X, and Pandora have not been tested recently and may have bitrot. OpenSolaris was previously mentioned in the list of working platforms, but neither old OpenSolaris nor modern Solaris can be verified currently. MegaZeux builds in ancient environments with a little manual effort, if for some reason you actually need this. The oldest tested is CentOS 3: - Partial triage has been done on GCC 3.2 and 3.3, but this is low priority: - 3.3: `-Wextra` added in 3.4 (trivial but left as a canary) - 3.3: `-Wdeclaration-after-statement` added in 3.4 - 3.3: requires `--disable-stack-protector` - 3.3: requires `--disable-modular` (`CORE_LIBSPEC export struct graphics graphics_data` doesn't work) - 3.2: `-std=gnu++98` added in 3.3 - 3.2: `-Wunused-macros` added in 3.3 - 3.2: `__attribute__(visibility("default"))` also doesn't work - **zlib** <1.2.0 requires replacing/disabling `deflateBound` and `infback9` - The numeric version macros didn't exist at this point; `ZLIB_VERNUM` was added in 1.2.0.2 and the rest later. - **libpng** <1.2.3 works if `libpng-config` is backported or if `LIBPNG_CFLAGS` and `LIBPNG_LDFLAGS` are manually supplied to `platform.inc`. - **libvorbis**: <1.2.2 works if `vorbis_version_string` is manually disabled. libvorbis has never had numeric version macros to test. ================================================ FILE: LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. ================================================ FILE: Makefile ================================================ ## # MegaZeux Build System (GNU Make) # # NOTE: This build system is designed to not use recursive Makefiles. # The rationale for this is documented here: # # https://web.archive.org/web/20200128044903/http://aegis.sourceforge.net/auug97.pdf ## # # Remove all built-in rules. # .SUFFIXES: ifeq ($(filter -r,$(MAKEFLAGS)),) MAKEFLAGS += -r endif .PHONY: all clean help_check mzx mzx.debug build build_clean source .PHONY: test testworlds unit unittest test_clean unit_clean # # Define this first so arch-specific rules don't hijack the default target. # all: -include platform.inc include version.inc # # ${build_root}: base location where builds are copied to be archived for release. # ${build}: location where the MegaZeux executable and data files should be placed. # Defaults to ${build_root}, but the architecture Makefile may override this to # use a subdirectory instead. This is useful when a platform expects a particular # path hierarchy within the archive (e.g. MacOS .app bundles). # build_root := build/${SUBPLATFORM} build := ${build_root} EXTRA_LICENSES ?= LICENSE_CC0 ?= arch/LICENSE.CC0 LICENSE_DJGPP ?= arch/LICENSE.DJGPP LICENSE_LGPL2 ?= arch/LICENSE.LGPL2 LICENSE_MPL2 ?= arch/LICENSE.MPL2 LICENSE_NEWLIB ?= arch/LICENSE.Newlib -include arch/${PLATFORM}/Makefile.in CC ?= gcc CXX ?= g++ AR ?= ar AS ?= as STRIP ?= strip OBJCOPY ?= objcopy WINDRES ?= windres PEFIX ?= true CHMOD ?= chmod CP ?= cp HOST_CC ?= gcc LN ?= ln MKDIR ?= mkdir MV ?= mv RM ?= rm ifneq (${CROSS_COMPILE},) ifeq (${CC},cc) CC = gcc endif CC := ${CROSS_COMPILE}${CC} CXX := ${CROSS_COMPILE}${CXX} AR := ${CROSS_COMPILE}${AR} AS := ${CROSS_COMPILE}${AS} STRIP := ${CROSS_COMPILE}${STRIP} OBJCOPY := ${CROSS_COMPILE}${OBJCOPY} WINDRES := ${CROSS_COMPILE}${WINDRES} endif include arch/compat.inc # # Set up CFLAGS/LDFLAGS for all MegaZeux external dependencies. # ifneq (${BUILD_SDL},) # # SDL 3 # ifeq (${BUILD_SDL},3) # Check SDL_PKG_CONFIG_PATH and PREFIX/lib/pkgconfig for sdl3.pc. # Note --with-path is a pkgconf extension. ifneq ($(and ${SDL_PKG_CONFIG_PATH},$(wildcard ${SDL_PKG_CONFIG_PATH}/sdl3.pc)),) # nop else # Check dependencies prefix instead for LIBDIR=. platforms. # This is useless for unix/darwin, which should have sdl3.pc in a # place pkgconf can find through normal means. ifeq (${LIBDIR},.) ifneq ($(wildcard ${PREFIX}/lib/pkgconfig/sdl3.pc),) SDL_PKG_CONFIG_PATH ?= ${PREFIX}/lib/pkgconfig endif endif # LIBDIR=. endif ifneq (${SDL_PKG_CONFIG_PATH},) SDL_PKG_CONFIG_FLAGS = --with-path=${SDL_PKG_CONFIG_PATH} SDL_PKG_CONFIG_FORCE := PKG_CONFIG_PATH="${SDL_PKG_CONFIG_PATH}" else SDL_PKG_CONFIG_FORCE := endif SDL_PREFIX := $(shell ${SDL_PKG_CONFIG_FORCE} ${PKGCONF} ${SDL_PKG_CONFIG_FLAGS} sdl3 --variable=prefix) SDL_CFLAGS ?= $(shell ${SDL_PKG_CONFIG_FORCE} ${PKGCONF} ${SDL_PKG_CONFIG_FLAGS} sdl3 --cflags) SDL_LDFLAGS ?= $(shell ${SDL_PKG_CONFIG_FORCE} ${PKGCONF} ${SDL_PKG_CONFIG_FLAGS} sdl3 --libs) endif # SDL3 # # SDL 2 # ifeq (${BUILD_SDL},2) # Check PREFIX for sdl2-config. ifneq ($(and ${SDL_PREFIX},$(wildcard ${SDL_PREFIX}/bin/sdl2-config)),) SDL_CONFIG := ${SDL_PREFIX}/bin/sdl2-config else ifneq ($(wildcard ${PREFIX}/bin/sdl2-config),) SDL_CONFIG := ${PREFIX}/bin/sdl2-config else SDL_CONFIG := sdl2-config endif endif SDL_PREFIX ?= $(shell ${SDL_CONFIG} --prefix) SDL_CFLAGS ?= $(shell ${SDL_CONFIG} --prefix=${SDL_PREFIX} --cflags | sed 's,-I,-isystem ,g') SDL_LDFLAGS ?= $(shell ${SDL_CONFIG} --prefix=${SDL_PREFIX} --libs) endif # SDL2 # # SDL 1.2 # ifeq (${BUILD_SDL},1) EXTRA_LICENSES += ${LICENSE_LGPL2} # Check PREFIX for sdl-config. ifneq ($(and ${SDL_PREFIX},$(wildcard ${SDL_PREFIX}/bin/sdl-config)),) SDL_CONFIG := ${SDL_PREFIX}/bin/sdl-config else ifneq ($(wildcard ${PREFIX}/bin/sdl-config),) SDL_CONFIG := ${PREFIX}/bin/sdl-config else SDL_CONFIG := sdl-config endif endif SDL_PREFIX ?= $(shell ${SDL_CONFIG} --prefix) SDL_CFLAGS ?= $(shell ${SDL_CONFIG} --prefix=${SDL_PREFIX} --cflags | sed 's,-I,-isystem ,g') SDL_LDFLAGS ?= $(shell ${SDL_CONFIG} --prefix=${SDL_PREFIX} --libs) endif # SDL1 # Make these immediate so the scripts run only once. SDL_PREFIX := $(SDL_PREFIX) SDL_CFLAGS := $(SDL_CFLAGS) SDL_LDFLAGS := $(LINK_DYNAMIC_IF_MIXED) $(SDL_LDFLAGS) endif # SDL # # libvorbis/tremor/stb_vorbis # VORBIS_CFLAGS ?= -I${PREFIX}/include -DOV_EXCLUDE_STATIC_CALLBACKS ifeq (${VORBIS},vorbis) VORBIS_LDFLAGS ?= $(LINK_STATIC_IF_MIXED) -L${PREFIX}/lib -lvorbisfile -lvorbis -logg endif ifeq (${VORBIS},tremor) VORBIS_LDFLAGS ?= $(LINK_STATIC_IF_MIXED) -L${PREFIX}/lib -lvorbisidec -logg endif ifeq (${VORBIS},tremor-lowmem) VORBIS_LDFLAGS ?= $(LINK_STATIC_IF_MIXED) -L${PREFIX}/lib -lvorbisidec endif ifeq (${VORBIS},stb_vorbis) VORBIS_LDFLAGS ?= -L${PREFIX}/lib endif # # MikMod (optional mod engine) # MIKMOD_CFLAGS ?= -I${PREFIX}/include MIKMOD_LDFLAGS ?= $(LINK_STATIC_IF_MIXED) -L${PREFIX}/lib -lmikmod ifneq (${BUILD_MIKMOD},) EXTRA_LICENSES += ${LICENSE_LGPL2} endif # # libopenmpt (optional mod engine) # OPENMPT_CFLAGS ?= -I${PREFIX}/include OPENMPT_LDFLAGS ?= $(LINK_STATIC_IF_MIXED) -L${PREFIX}/lib -lopenmpt # # zlib # ZLIB_CFLAGS ?= -I${PREFIX}/include ZLIB_LDFLAGS ?= $(LINK_STATIC_IF_MIXED) -L${PREFIX}/lib -lz # # libpng # ifeq (${LIBPNG},1) # Check PREFIX for libpng-config. ifneq ($(and ${LIBPNG_PREFIX},$(wildcard ${LIBPNG_PREFIX}/bin/libpng-config)),) LIBPNG_CONFIG := ${LIBPNG_PREFIX}/bin/libpng-config else ifneq ($(wildcard ${PREFIX}/bin/libpng-config),) LIBPNG_CONFIG := ${PREFIX}/bin/libpng-config else LIBPNG_CONFIG := libpng-config endif endif LIBPNG_CFLAGS ?= $(shell ${LIBPNG_CONFIG} --cflags) LIBPNG_LDFLAGS ?= $(shell ${LIBPNG_CONFIG} --ldflags) # Make these immediate so the scripts run only once. LIBPNG_CFLAGS := $(LIBPNG_CFLAGS) LIBPNG_LDFLAGS := $(LINK_STATIC_IF_MIXED) $(LIBPNG_LDFLAGS) endif # # X11 # ifneq (${X11DIR},) # BSD needs this but Fedora rpmbuild will whine about it and fail. ifneq (${X11DIR},/usr) X11RPATH ?= -Wl,-rpath,${X11LIBDIR} endif X11_CFLAGS ?= -I${X11DIR}/include X11_LDFLAGS ?= -L${X11LIBDIR} -lX11 ${X11RPATH} # Make these immediate X11_CFLAGS := $(X11_CFLAGS) X11_LDFLAGS := $(X11_LDFLAGS) endif # # pthread # PTHREAD_LDFLAGS ?= -lpthread # # Set up general CFLAGS/LDFLAGS # # # Usually, just disable the optimizer for "true" debug builds and # define "DEBUG" to enable optional code at compile time. # Optimized builds have assert() compiled out. # ifneq (${DEBUG},1) OPTIMIZE_FLAGS := -O3 ${OPTIMIZE_CFLAGS} ${OPTIMIZE_FLAGS} OPTIMIZE_DEF ?= -DNDEBUG else OPTIMIZE_FLAGS := -O0 ${DEBUG_CFLAGS} ${OPTIMIZE_FLAGS} OPTIMIZE_DEF ?= -DDEBUG endif # # Enable a sanitizer and its corresponding extra options, if selected. # ifeq (${SANITIZER},address) OPTIMIZE_FLAGS += -fsanitize=address -fno-omit-frame-pointer endif ifeq (${SANITIZER},undefined) # Signed integer overflows (shift-base, signed-integer-overflow) # are pretty much inevitable in Robotic, so ignore them. OPTIMIZE_FLAGS += -fsanitize=undefined -fno-omit-frame-pointer \ -fno-sanitize-recover=all -fno-sanitize=shift-base,signed-integer-overflow endif ifeq (${SANITIZER},thread) OPTIMIZE_FLAGS += -fsanitize=thread -fno-omit-frame-pointer -fPIE ARCH_EXE_LDFLAGS += -pie endif ifeq (${SANITIZER},memory) # Note: to be useful, this requires a fairly special build with most # external libraries turned off or re-built with instrumentation. # This sanitizer is only implemented by clang. OPTIMIZE_FLAGS += -fsanitize=memory -fno-omit-frame-pointer -fPIC \ -fsanitize-memory-track-origins=2 ARCH_EXE_LDFLAGS += -pie endif # # Enable link-time optimization. # ifeq (${LTO},1) ifeq (${HAS_F_LTO},1) OPTIMIZE_FLAGS += -flto else $(warning link-time optimization not supported, ignoring.) endif endif CFLAGS += ${OPTIMIZE_FLAGS} ${OPTIMIZE_DEF} CXXFLAGS += ${OPTIMIZE_FLAGS} ${OPTIMIZE_DEF} LDFLAGS += ${OPTIMIZE_FLAGS} # # Enable C++11 for compilers that support it. # Anything actually using C++11 should be optional or platform-specific, # as features using C++11 reduce portability. # ifeq (${HAS_CXX_11},1) CXX_STD = -std=gnu++11 else CXX_STD = -std=gnu++98 endif # # Always generate debug information; this may end up being # stripped (on embedded platforms) or objcopy'ed out. # CFLAGS += -std=gnu99 -g ${ARCH_CFLAGS} CXXFLAGS += ${CXX_STD} -g -fno-exceptions -fno-rtti ${ARCH_CXXFLAGS} LDFLAGS += ${ARCH_LDFLAGS} # # Default warnings. # Note: -Wstrict-prototypes was previously turned off for Android/NDS/Wii/PSP. # warnings := -Wall -Wextra -Wno-unused-parameter -Wwrite-strings warnings += -Wundef -Wunused-macros -Wpointer-arith CFLAGS += ${warnings} -Wdeclaration-after-statement -Wmissing-prototypes -Wstrict-prototypes CXXFLAGS += ${warnings} # # Optional compile flags. # # # Warn against global functions defined without a previous declaration (C++). # ifeq (${HAS_W_MISSING_DECLARATIONS_CXX},1) CXXFLAGS += -Wmissing-declarations endif # # Warn against variable-length array (VLA) usage, which is technically valid # C99 but is in bad taste and isn't supported by MSVC. # ifeq (${HAS_W_VLA},1) CFLAGS += -Wvla CXXFLAGS += -Wvla endif # # Linux GCC gives spurious format truncation warnings. The snprintf # implementation on Linux will terminate even in the case of truncation, # making this largely useless. It does not trigger using mingw (where it # would actually matter). # ifeq (${HAS_W_NO_FORMAT_TRUNCATION},1) CFLAGS += -Wno-format-truncation CXXFLAGS += -Wno-format-truncation endif # # Old GCC versions emit false positive warnings for C++11 value initializers. # ifeq (${HAS_BROKEN_W_MISSING_FIELD_INITIALIZERS},1) CXXFLAGS += -Wno-missing-field-initializers endif # # We enable pedantic warnings here, but this ends up turning on some things # we must disable by hand. # # Variadic macros are arguably less portable, but all the compilers we # support have them. # ifeq (${HAS_PEDANTIC},1) CFLAGS += -pedantic CXXFLAGS += -pedantic ifeq (${HAS_W_NO_VARIADIC_MACROS},1) CFLAGS += -Wno-variadic-macros CXXFLAGS += -Wno-variadic-macros endif endif # # KallistiOS has a pretty dire header situation # ifeq (${BUILD_DREAMCAST},1) CFLAGS += -Wno-strict-prototypes -Wno-pedantic CXXFLAGS += -Wno-pedantic endif # # As does BlocksDS, currently # ifeq (${BUILD_NDS_BLOCKSDS},1) CFLAGS += -Wno-strict-prototypes -Wno-pedantic -Wno-declaration-after-statement CXXFLAGS += -Wno-pedantic endif # # The following flags are not applicable to mingw or djgpp builds. # ifneq (${PLATFORM},mingw) ifneq (${PLATFORM},djgpp) # # Symbols in COFF binaries are implicitly hidden unless exported; this # flag just confuses GCC and must be disabled. # ifeq (${HAS_F_VISIBILITY},1) CFLAGS += -fvisibility=hidden CXXFLAGS += -fvisibility=hidden endif endif # PLATFORM=djgpp endif # PLATFORM=mingw # # The stack protector is optional and is generally only built for Linux/BSD and # Mac OS X. It also works on Windows. GCC's -fstack-protector-strong is # preferred when available due to better performance. # ifeq (${BUILD_STACK_PROTECTOR},1) ifeq (${HAS_F_STACK_PROTECTOR_STRONG},1) CFLAGS += -fstack-protector-strong CXXFLAGS += -fstack-protector-strong else ifeq (${HAS_F_STACK_PROTECTOR},1) CFLAGS += -fstack-protector-all CXXFLAGS += -fstack-protector-all else $(warning stack protector not supported, ignoring.) endif endif endif # # Enable -fanalyzer if supported. # ifeq (${BUILD_F_ANALYZER},1) ifeq (${HAS_F_ANALYZER},1) CFLAGS += -fanalyzer CXXFLAGS += -fanalyzer else $(warning GCC 10+ is required for -fanalyzer, ignoring.) endif endif # # Enable position-independent code across the board for modular builds. # ifeq (${BUILD_MODULAR},1) CFLAGS += -fPIC CXXFLAGS += -fPIC endif # # We don't want these commands to be echo'ed in non-verbose mode # ifneq (${V},1) override V:= CC := @${CC} CXX := @${CXX} AR := @${AR} AS := @${AS} STRIP := @${STRIP} OBJCOPY := @${OBJCOPY} WINDRES := @${WINDRES} PEFIX := @${PEFIX} CHMOD := @${CHMOD} CP := @${CP} HOST_CC := @${HOST_CC} LN := @${LN} MKDIR := @${MKDIR} MV := @${MV} RM := @${RM} endif build_clean: $(if ${V},,@echo " RM " build) ${RM} -r build source: build/${TARGET}src # # Build source target # Targeting unix primarily, so turn off autocrlf if necessary. # build/${TARGET}src: ${RM} -r build/${TARGET} ${MKDIR} -p build/dist/source @git -c "core.autocrlf=false" checkout-index -a --prefix build/${TARGET}/ ${RM} -r build/${TARGET}/scripts ${RM} build/${TARGET}/.gitignore build/${TARGET}/.gitattributes @cd build/${TARGET} && ${MAKE} distclean @tar -C build -Jcf build/dist/source/${TARGET}src.tar.xz ${TARGET} # # The SUPPRESS_ALL_TARGETS hack is required to allow the placebo "dist" # Makefile to provide an 'all:' target, which allows it to print # a message. Pulling in any other targets would confuse Make. # # Additionally, there are several other SUPPRESS flags that can be set to # conditionally disable rules. This is useful for cross-compiling builds that # have no use for host-based rules or for platforms that use meta targets. # # * SUPPRESS_CC_TARGETS prevents "mzx", etc from being added to "all". # * SUPPRESS_BUILD_TARGETS suppresses "build". # * SUPPRESS_HOST_TARGETS suppresses "assets/help.fil", "test", etc. # ifneq (${SUPPRESS_ALL_TARGETS},1) mzxrun = mzxrun${BINEXT} mzx = megazeux${BINEXT} mzx: ${mzxrun} ${mzx} mzx.debug: ${mzxrun}.debug ${mzx}.debug ifeq (${BUILD_MODPLUG},1) BUILD_GDM2S3M=1 endif %/.build: $(if ${V},,@echo " MKDIR " $@) ${MKDIR} $@ %.debug: % $(if ${V},,@echo " OBJCOPY " --only-keep-debug $< $@) ${OBJCOPY} --only-keep-debug $< $@ ${PEFIX} $@ ${CHMOD} a-x $@ ifneq (${NO_STRIP_IN_DEBUGLINK},1) $(if ${V},,@echo " STRIP " --strip-unneeded $<) ${STRIP} --strip-unneeded $< endif $(if ${V},,@echo " OBJCOPY " --add-gnu-debuglink $@ $<) ${OBJCOPY} --add-gnu-debuglink=$@ $< ${PEFIX} $< @touch $@ include src/Makefile.in clean: mzx_clean test_clean unit_clean ifneq (${SUPPRESS_CC_TARGETS},1) all: mzx debuglink: all mzx.debug endif ifeq (${BUILD_UTILS},1) include src/utils/Makefile.in clean: utils_clean ifneq (${SUPPRESS_CC_TARGETS},1) debuglink: utils utils.debug all: utils endif endif ifneq (${SUPPRESS_BUILD_TARGETS},1) ifeq (${build},) build := ${build_root} endif .PHONY: ${build} build: ${build} ${build}/assets ${build}/docs ${build}: ${RM} -r ${build_root} ${MKDIR} -p ${build} ${CP} config.txt LICENSE arch/LICENSE.3rd ${EXTRA_LICENSES} ${build} @if test -f ${mzxrun}; then \ cp ${mzxrun} ${build}; \ fi @if test -f ${mzxrun}.debug; then \ cp ${mzxrun}.debug ${build}; \ fi ifeq (${BUILD_EDITOR},1) @if test -f ${mzx}; then \ cp ${mzx} ${build}; \ fi @if test -f ${mzx}.debug; then \ cp ${mzx}.debug ${build}; \ fi endif ifeq (${BUILD_MODULAR},1) ${CP} ${core_target} ${editor_target} ${build} @if test -f ${core_target}.debug; then \ cp ${core_target}.debug ${build}; \ fi @if test -f ${editor_target}.debug; then \ cp ${editor_target}.debug ${build}; \ fi endif ifeq (${BUILD_UTILS},1) ${MKDIR} ${build}/utils ${CP} ${checkres} ${downver} ${build}/utils ${CP} ${hlp2txt} ${txt2hlp} ${build}/utils ${CP} ${ccv} ${png2smzx} ${y4m2smzx} ${build}/utils @if [ -f "${checkres}.debug" ]; then cp ${checkres}.debug ${build}/utils; fi @if [ -f "${downver}.debug" ]; then cp ${downver}.debug ${build}/utils; fi @if [ -f "${hlp2txt}.debug" ]; then cp ${hlp2txt}.debug ${build}/utils; fi @if [ -f "${txt2hlp}.debug" ]; then cp ${txt2hlp}.debug ${build}/utils; fi @if [ -f "${ccv}.debug" ]; then cp ${ccv}.debug ${build}/utils; fi @if [ -f "${png2smzx}.debug" ]; then cp ${png2smzx}.debug ${build}/utils; fi @if [ -f "${y4m2smzx}.debug" ]; then cp ${y4m2smzx}.debug ${build}/utils; fi endif ${build}/docs: ${build} ${MKDIR} -p ${build}/docs ${CP} docs/macro.txt docs/keycodes.html docs/mzxhelp.html ${build}/docs ${CP} docs/joystick.html docs/cycles_and_commands.txt ${build}/docs ${CP} docs/fileform.html ${build}/docs ${CP} docs/changelog.txt docs/platform_matrix.html ${build}/docs ${build}/assets: ${build} ${MKDIR} -p ${build}/assets ${CP} assets/default.chr assets/edit.chr ${build}/assets ${CP} assets/smzx.pal ${build}/assets ifeq (${BUILD_EDITOR},1) ${CP} assets/ascii.chr assets/blank.chr ${build}/assets ${CP} assets/smzx.chr assets/smzx2.chr ${build}/assets endif ifeq (${BUILD_HELPSYS},1) ${CP} assets/help.fil ${build}/assets endif ifeq (${BUILD_RENDER_GL_PROGRAM},1) ${MKDIR} -p ${build}/assets/glsl/scalers ${CP} assets/glsl/*.vert ${build}/assets/glsl ${CP} assets/glsl/*.frag ${build}/assets/glsl ${CP} assets/glsl/README.md ${build}/assets/glsl ${CP} assets/glsl/scalers/*.frag assets/glsl/scalers/*.vert \ ${build}/assets/glsl/scalers endif ifeq (${BUILD_GAMECONTROLLERDB},1) ${CP} assets/gamecontrollerdb.txt \ ${build}/assets endif ifeq (${BUILD_UTILS},1) ${CP} contrib/mzvplay/mzvplay.txt \ ${build}/utils endif endif # !SUPPRESS_BUILD_TARGETS distclean: clean @echo " DISTCLEAN" @rm -f src/config.h @echo "PLATFORM=none" > platform.inc ifneq (${SUPPRESS_HOST_TARGETS},1) assets/help.fil: ${txt2hlp} docs/WIPHelp.txt $(if ${V},,@echo " txt2hlp " $@) @src/utils/txt2hlp docs/WIPHelp.txt $@ docs/mzxhelp.html: ${hlp2html} docs/WIPHelp.txt $(if ${V},,@echo " hlp2html" $@) @src/utils/hlp2html docs/WIPHelp.txt docs/mzxhelp.html help_check: ${hlp2txt} assets/help.fil @src/utils/hlp2txt assets/help.fil help.txt @echo @ >> help.txt @diff --strip-trailing-cr -q docs/WIPHelp.txt help.txt @rm -f help.txt -include unit/Makefile.in test: unit test testworlds: ifeq (${BUILD_MODULAR},1) @${SHELL} testworlds/run.sh ${PLATFORM} "$(realpath ${core_target})" else @${SHELL} testworlds/run.sh ${PLATFORM} endif endif # !SUPPRESS_HOST_TARGETS test_clean: @rm -rf testworlds/log endif # !SUPPRESS_ALL_TARGETS ================================================ FILE: README.md ================================================ # MegaZeux [Official MegaZeux git repository](https://github.com/AliceLR/megazeux) MegaZeux is a game creation system (GCS) created by game developer Alexis Janson in 1994. Originally a DOS program, in 2005 a multi-platform port was released by Exophase. The most recent version of MegaZeux is 2.93d, which was released on June 9th, 2025. MegaZeux is officially supported on Windows, Linux, macOS, BSD, Haiku, HTML5, and MS-DOS, as well as numerous console ports. See platform_matrix.html for a full list of ports. ## Downloads Windows, MS-DOS, and console releases are packaged with a copy of the game Caverns of Zeux. Older versions are available at [DigitalMZX](https://www.digitalmzx.com/) or [on the Github releases page](https://github.com/AliceLR/megazeux/releases). [megazeux-w64]: https://www.digitalmzx.com/download.php?latest=windows64 [megazeux-w32]: https://www.digitalmzx.com/download.php?latest=windows32 [megazeux-dos]: https://www.digitalmzx.com/download.php?latest=dos [megazeux-dos32]: https://www.digitalmzx.com/download.php?latest=dosdjgpp [megazeux-osx]: https://www.digitalmzx.com/download.php?latest=osx [megazeux-ppc]: https://www.digitalmzx.com/download.php?latest=osxppc [megazeux-u64]: https://www.digitalmzx.com/download.php?latest=ubuntu64 [megazeux-ults]: https://www.digitalmzx.com/download.php?latest=ubuntu64lts [megazeux-d64]: https://www.digitalmzx.com/download.php?latest=debian64 [megazeux-d32]: https://www.digitalmzx.com/download.php?latest=debian32 [megazeux-f64]: https://www.digitalmzx.com/download.php?latest=fedora64 [megazeux-rpi]: https://www.digitalmzx.com/download.php?latest=raspbian [megazeux-flat]: https://www.digitalmzx.com/download.php?latest=flatpak [megazeux-and]: https://www.digitalmzx.com/download.php?latest=android [megazeux-html]: https://www.digitalmzx.com/download.php?latest=html5 [megazeux-nds]: https://www.digitalmzx.com/download.php?latest=nds [megazeux-3ds]: https://www.digitalmzx.com/download.php?latest=3ds [megazeux-wii]: https://www.digitalmzx.com/download.php?latest=wii [megazeux-wiiu]: https://www.digitalmzx.com/download.php?latest=wiiu [megazeux-swi]: https://www.digitalmzx.com/download.php?latest=switch [megazeux-psp]: https://www.digitalmzx.com/download.php?latest=psp [megazeux-vita]: https://www.digitalmzx.com/download.php?latest=psvita [megazeux-dc]: https://www.digitalmzx.com/download.php?latest=dreamcast [megazeux-src]: https://www.digitalmzx.com/download.php?latest=src [arch-w64]: contrib/archicons/windows64.png "Windows x64" [arch-w32]: contrib/archicons/windows32.png "Windows x86" [arch-dos]: contrib/archicons/dos.png "MS DOS (MZX 2.70)" [arch-dos32]:contrib/archicons/dosdjgpp.png "MS DOS (32-bit)" [arch-osx]: contrib/archicons/osx.png "macOS" [arch-ppc]: contrib/archicons/maccompat.png "macOS (Compatible)" [arch-u64]: contrib/archicons/ubuntu64.png "Ubuntu AMD64" [arch-ults]: contrib/archicons/ubuntu64lts.png "Ubuntu AMD64 LTS" [arch-d64]: contrib/archicons/debian64.png "Debian AMD64" [arch-d32]: contrib/archicons/debian32.png "Debian i386" [arch-f64]: contrib/archicons/fedora64.png "Fedora x86_64" [arch-rpi]: contrib/archicons/raspbian.png "Raspbian" [arch-flat]:contrib/archicons/flatpak.png "Flatpak" [arch-and]: contrib/archicons/android.png "Android" [arch-html]:contrib/archicons/html5.png "HTML5 (Emscripten)" [arch-aur]: contrib/archicons/archlinux.png "Arch Linux (via AUR)" [arch-void]:contrib/archicons/voidlinux.png "Void Linux" [arch-gen]: contrib/archicons/gentoo.png "Gentoo" [arch-alp]: contrib/archicons/alpine.png "Alpine Linux" [arch-nds]: contrib/archicons/nds.png "Nintendo DS" [arch-3ds]: contrib/archicons/3ds.png "Nintendo 3DS" [arch-wii]: contrib/archicons/wii.png "Nintendo Wii" [arch-wiiu]:contrib/archicons/wiiu.png "Nintendo Wii U" [arch-swi]: contrib/archicons/switch.png "Nintendo Switch" [arch-psp]: contrib/archicons/psp.png "PlayStation Portable" [arch-vita]:contrib/archicons/psvita.png "PlayStation Vita" [arch-dc]: contrib/archicons/dreamcast.png "Sega Dreamcast" [arch-ami]: contrib/archicons/amiga.png "Amiga OS 4" [arch-gp2x]:contrib/archicons/gp2x.png "GP2X" [arch-pand]:contrib/archicons/pandora.png "Pandora" [arch-src]: contrib/archicons/src.png "Source code"   [![Windows x64 ][arch-w64]][megazeux-w64]   [![Windows x86 ][arch-w32]][megazeux-w32]   [![Mac OS X ][arch-osx]][megazeux-osx]   [![macOS (Compatible)) ][arch-ppc]][megazeux-ppc]   [![Ubuntu AMD64 ][arch-u64]][megazeux-u64]   [![Ubuntu AMD64 LTS ][arch-ults]][megazeux-ults]   [![Debian AMD64 ][arch-d64]][megazeux-d64]   [![Debian i386 ][arch-d32]][megazeux-d32]   [![Fedora x86_64 ][arch-f64]][megazeux-f64]   [![Raspbian ][arch-rpi]][megazeux-rpi]   [![Flatpak ][arch-flat]][megazeux-flat]   [![Android ][arch-and]][megazeux-and]   [![HTML5 (Emscripten) ][arch-html]][megazeux-html]   [![Nintendo DS ][arch-nds]][megazeux-nds]   [![Nintendo 3DS ][arch-3ds]][megazeux-3ds]   [![Nintendo Wii ][arch-wii]][megazeux-wii]   [![Nintendo Wii U ][arch-wiiu]][megazeux-wiiu]   [![Nintendo Switch ][arch-swi]][megazeux-swi]   [![PlayStation Portable][arch-psp]][megazeux-psp]   [![PlayStation Vita ][arch-vita]][megazeux-vita]   [![Sega Dreamcast ][arch-dc]][megazeux-dc]   [![DOS (32-bit) ][arch-dos32]][megazeux-dos32]   [![MS DOS (MZX 2.70) ][arch-dos]][megazeux-dos]   [![Source code ][arch-src]][megazeux-src] The following platforms have MegaZeux releases available via repository:   [![Arch Linux (via AUR)][arch-aur]](https://aur.archlinux.org/packages/megazeux/)   [![Void Linux][arch-void]](https://github.com/void-linux/void-packages/tree/master/srcpkgs/megazeux)   [![Gentoo][arch-gen]](https://github.com/Spectere/megazeux-overlay)   [![Alpine Linux][arch-alp]](https://pkgs.alpinelinux.org/packages?name=megazeux)   [![Amiga OS 4 (outdated)][arch-ami]](http://aminet.net/package/game/misc/pfp-mgzx)   [![GP2X (outdated)][arch-gp2x]](https://dl.openhandhelds.org/cgi-bin/gp2x.cgi?0,0,0,0,26,2920)   [![Pandora (outdated)][arch-pand]](https://repo.openpandora.org/?page=detail&app=megazeux_ptitseb) ## Building MegaZeux See BUILDING.md for more information about compiling MegaZeux from source. ## Credits | MegaZeux 2.9x | | | ----------------------- | ---------------------------------------------------------- | | Alice Rowan | Development/current maintainer | | Terryn | Help file; testing | | Lancer X | Development; testing | | Adrian Siekierka | Development; testing; various ports | | Dizzy O'Malley-Morrison | Development; testing; Ubuntu/Debian/Raspbian/Arch packages | | Spectere | Development; testing; Xcode and MSVC projects | | Alistair Strachan | Development | | Others | Various | #### MegaZeux Credits Programming and Overall Design by Gilead Kutnick (Exophase), Alistair Strachan (ajs), Alice Rowan (Lachesis) and Lancer-X. Based off of original program and source code by Alexis Janson. Help file by Terryn. Default SMZX palette by Joel Lamontagne (LogiCow). ccv utility by Lancer-X. png2smzx utility by Alan Williams (Mr_Alert). checkres utility by Josh Matthews (Revvy), ajs and Lachesis. Port contributors: Adrian Siekierka (asiekierka) [3DS], Mr_Alert [Wii], Kevin Vance [NDS], Simon Parzer [GP2X]. Renderer code contributors: LogiCow, Mr_Alert. Shader code contributors: David Cravens (astral), GreaseMonkey. Icon by Quantum P.; Extra icons by LogiCow. GDM conversion by ajs and MadBrain. Other past contributors: Spider124, Koji, JZig, Akwende, MenTaLguY. #### Special Thanks Dizzy (Testing, .deb and Arch packages) Spectere (Testing, OS X Builds, MSVC project) Terryn (Testing) mzxgiant (MSVC Testing, Bug Fixes) mzxrules (Testing) Quantum P. (OS X Testing / Builds) Wervyn (Testing) ## License This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ## Contact Want to talk about MegaZeux? Encountered a bug or would like a new feature? The MegaZeux community and development team can be contacted through Discord, GitHub, or the DigitalMZX forums. [MegaZeux Discord](https://discord.gg/XJCvb4P)
[DigitalMZX forums](https://www.digitalmzx.com/forums/)
[MegaZeux Bug tracker](https://www.digitalmzx.com/forums/index.php?app=tracker&showproject=4)
[MegaZeux Feature requests](https://www.digitalmzx.com/forums/index.php?app=tracker&showproject=9)
[AliceLR on GitHub](https://github.com/AliceLR)
## Resources [Official MegaZeux game archive](https://www.digitalmzx.com/)
[MegaZeux help file](https://www.digitalmzx.com/mzx_help.html)
[Development roadmap](https://www.digitalmzx.com/forums/index.php?showtopic=15226) ================================================ FILE: arch/3ds/CONFIG.3DS ================================================ #!/bin/sh ./config.sh --platform 3ds --enable-release --enable-lto --enable-meter \ --disable-sdl --enable-tremor --disable-screenshots --disable-utils \ --enable-stdio-redirect "$@" ================================================ FILE: arch/3ds/Makefile.in ================================================ # # Nintendo 3DS Makefile # include $(DEVKITARM)/3ds_rules .PHONY: package clean ifeq ($(strip $(DEVKITPRO)),) $(error "DEVKITPRO must be set in your environment.") endif ifeq ($(strip $(DEVKITARM)),) $(error "DEVKITARM must be set in your environment.") endif ifneq (${BUILD_EDITOR},) APP_TITLE_MZX = MegaZeux APP_TITLE_MZXRUN = MegaZeux (MZXRun) else APP_TITLE_MZXRUN = MegaZeux endif APP_DESCRIPTION = Game creation system APP_AUTHOR = MegaZeux Developers APP_ICON = contrib/icons/generated/icon_48.png EXTRA_LICENSES += ${LICENSE_MPL2} ${LICENSE_NEWLIB} # # 3DS target rules # # Block --host, which will break things. CROSS_COMPILE = # Don't strip when generating debug symbols. NO_STRIP_IN_DEBUGLINK ?= 1 # Disable rules that require target code to run natively. SUPPRESS_HOST_TARGETS ?= 1 # # Override library paths. # # # As of devkitARM r51 $(PORTLIBS) has multiple paths... # PORTLIBS_INCLUDES := $(foreach dir, $(PORTLIBS), -isystem $(dir)/include) PORTLIBS_LIBS := $(foreach dir, $(PORTLIBS), -L$(dir)/lib) EXTRA_INCLUDES := -isystem $(CTRULIB)/include ${PORTLIBS_INCLUDES} EXTRA_LIBS := -L$(CTRULIB)/lib ${PORTLIBS_LIBS} ifeq (${DEBUG},1) EXTRA_LIBS += -lcitro3dd -lctrud -lpng16 -lz else OPTIMIZE_FLAGS += -fomit-frame-pointer -ffunction-sections EXTRA_LIBS += -lcitro3d -lctru -lpng16 -lz endif MACHDEP = -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft -mword-relocations ifneq (${BUILD_SDL},) # devkitPro's SDL 1.2 port accidentally defines key_press and key_release as # global symbols. 3DS_CFLAGS += -Dkey_press=mzx_key_press -Dkey_release=mzx_key_release endif 3DS_CFLAGS += ${EXTRA_INCLUDES} ${MACHDEP} -DARM11 -D__3DS__ -Iarch/3ds ARCH_CFLAGS += ${3DS_CFLAGS} ARCH_CXXFLAGS += ${3DS_CFLAGS} ARCH_LDFLAGS += ${EXTRA_LIBS} ${MACHDEP} -specs=3dsx.specs LIBPNG_CFLAGS = LIBPNG_LDFLAGS = -lpng16 # # Vile hack, remove me ASAP # (also, vile hack in a vile hack to get the shaders to build parallel) # arch/3ds/%.o: arch/3ds/%.c $(if ${V},,@echo " CC " $<) ${CC} -MD ${core_cflags} ${core_flags} -Wno-unused-macros -c $< -o $@ arch/3ds/%.o: arch/3ds/%.cpp arch/3ds/shader_2d.shbin.o arch/3ds/shader_playfield.shbin.o $(if ${V},,@echo " CXX " $<) ${CXX} -MD ${core_cxxflags} ${core_flags} -Wno-unused-macros -c $< -o $@ # Do not delete these, since doing so will retrigger .o rebuilds above .SECONDARY: arch/3ds/shader_2d_shbin.h arch/3ds/shader_playfield_shbin.h arch/3ds/%.shbin: arch/3ds/%.v.pica arch/3ds/%.g.pica $(if ${V},,@echo " PICASSO " $^) @picasso -o $@ $^ arch/3ds/%.shbin.o: arch/3ds/%.shbin arch/3ds/%_shbin.h $(if ${V},,@echo " AS " $<) @bin2s $< > $<.S @# Shut up the assembler since bin2s doesn't emit a trailing newline: @echo '' >> $<.S $(AS) $<.S -o $@ arch/3ds/%_shbin.h: arch/3ds/%.shbin $(eval CURLOC := $(patsubst %_shbin.h,%.shbin,$@)) $(eval CURBIN := $(patsubst %_shbin.h,%.shbin,$(notdir $@))) $(if ${V},,@echo " ECHO " $@) @echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURLOC) | tr . _)`.h @echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURLOC) | tr . _)`.h @echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURLOC) | tr . _)`.h # # Target-specific variables to force the .3dsx files to have different titles... # mzxrun.smdh: APP_TITLE=${APP_TITLE_MZXRUN} megazeux.smdh: APP_TITLE=${APP_TITLE_MZX} package: mzx mzxrun.smdh megazeux.smdh 3dsxtool ${mzxrun} ${mzxrun}.3dsx --smdh=${mzxrun}.smdh --romfs=arch/3ds/romfs ifneq (${BUILD_EDITOR},) 3dsxtool ${mzx} ${mzx}.3dsx --smdh=${mzx}.smdh --romfs=arch/3ds/romfs endif clean: ${RM} ${mzxrun}.smdh ${mzxrun}.3dsx ${mzx}.smdh ${mzx}.3dsx ${RM} arch/3ds/*.d arch/3ds/*.o arch/3ds/*shbin* build := ${build_root}/3ds/megazeux build: package ${build} ifeq ($(BUILD_SDL),) ${CP} arch/3ds/pad.config ${build} else ifeq ($(BUILD_SDL),1) ${CP} arch/3ds/pad.config.sdl12 ${build}/pad.config else ${CP} arch/3ds/pad.config.sdl2 ${build}/pad.config endif endif ${CP} ${mzxrun}.3dsx ${build} ifneq (${BUILD_EDITOR},) ${CP} ${mzx}.3dsx ${build} endif ${RM} ${build}/${mzxrun} ${build}/${mzxrun}.debug ${RM} ${build}/${mzx} ${build}/${mzx}.debug include arch/zip.inc ================================================ FILE: arch/3ds/README.md ================================================ ## Preparation You need to install the latest versions of the devkitARM toolchain, as well as the necessary 3DS tooling. You also need to install zlib, libpng and libtremor. This can be done with the following command: pacman -S 3ds-libogg 3ds-libpng 3ds-libvorbisidec 3ds-zlib ## Configuring See CONFIG.3DS for an optimal `config.sh` configure line. You need to ensure DEVKITPRO and DEVKITARM are both defined and valid. ## Building For the moment, you need to build with: make package This will emit the "mzxrun.3dsx" file. ## Packaging You can then use the usual `make archive` to build a build/dist/3ds/mzxgit-3ds.zip file for distribution. ================================================ FILE: arch/3ds/audio.c ================================================ /* MegaZeux * * Copyright (C) 2016 Adrian Siekierka * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "../../src/event.h" #include "../../src/platform.h" #include "../../src/graphics.h" #include "../../src/audio/audio.h" #include "../../src/audio/audio_struct.h" #include <3ds.h> #include #include "platform.h" #ifdef CONFIG_AUDIO static u8 *audio_buffer; static ndspWaveBuf ndsp_buffer[2]; static unsigned buffer_frames; static unsigned buffer_size; static bool soundFillBlock = false; static void ndsp_callback(void *dud) { if(ndsp_buffer[soundFillBlock].status == NDSP_WBUF_DONE) { audio_mixer_render_frames(ndsp_buffer[soundFillBlock].data_pcm16, buffer_frames, 2, SAMPLE_S16); DSP_FlushDataCache(ndsp_buffer[soundFillBlock].data_pcm8, buffer_size); ndspChnWaveBufAdd(0, &ndsp_buffer[soundFillBlock]); soundFillBlock = !soundFillBlock; } } void init_audio_platform(struct config_info *conf) { // buffer size must be multiple of 32 bytes(?), so samples must be multiple of 8 unsigned frames = (conf->audio_buffer_samples + 7) & ~7; float mix[12]; audio_buffer = NULL; if(!audio_mixer_init(conf->audio_sample_rate, frames, 2)) return; buffer_frames = audio.buffer_frames; buffer_size = buffer_frames * sizeof(int16_t) * 2 /* stereo */; if(ndspInit() != 0) return; memset(mix, 0, sizeof(mix)); mix[0] = mix[1] = 1.0f; ndspSetOutputMode(NDSP_OUTPUT_STEREO); ndspSetOutputCount(1); ndspSetMasterVol(1.0f); audio_buffer = clinearAlloc(buffer_size * 2, 0x80); memset(audio_buffer, 0, buffer_size * 2); ndspSetCallback(ndsp_callback, audio_buffer); memset(&ndsp_buffer[0], 0, sizeof(ndspWaveBuf)); memset(&ndsp_buffer[1], 0, sizeof(ndspWaveBuf)); ndspChnReset(0); ndspChnSetInterp(0, NDSP_INTERP_LINEAR); ndspChnSetRate(0, audio.output_frequency); ndspChnSetFormat(0, NDSP_CHANNELS(2) | NDSP_ENCODING(NDSP_ENCODING_PCM16)); ndspChnSetMix(0, mix); ndsp_buffer[0].data_vaddr = &audio_buffer[0]; ndsp_buffer[0].nsamples = buffer_frames; ndsp_buffer[1].data_vaddr = &audio_buffer[buffer_size]; ndsp_buffer[1].nsamples = buffer_frames; ndspChnWaveBufAdd(0, &ndsp_buffer[0]); ndspChnWaveBufAdd(0, &ndsp_buffer[1]); } void quit_audio_platform(void) { if(audio_buffer) { linearFree(audio_buffer); audio_buffer = NULL; ndspExit(); } } #endif // CONFIG_AUDIO ================================================ FILE: arch/3ds/event.c ================================================ /* MegaZeux * * Copyright (C) 2016 Adrian Siekierka * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "../../src/event.h" #include "../../src/graphics.h" #include "../../src/platform.h" #include "../../src/util.h" #include <3ds.h> #include #include "event.h" #include "keyboard.h" extern struct input_status input; static enum bottom_screen_mode b_mode; static enum focus_mode allow_focus_changes = FOCUS_ALLOW; static boolean is_dragging = false; boolean update_hid(void); enum focus_mode get_allow_focus_changes(void) { return allow_focus_changes; } enum bottom_screen_mode get_bottom_screen_mode(void) { return b_mode; } boolean __update_event_status(void) { boolean retval = false; retval |= aptMainLoop(); retval |= update_hid(); return retval; } boolean __peek_exit_input(void) { /* FIXME stub */ return false; } void __wait_event(void) { while(!__update_event_status()) gspWaitForVBlank(); } void __warp_mouse(int x, int y) { // Since the touchscreen stylus can't be warped, focus there instead. focus_pixel(x, y); } // Convert the 3DS axis ranges to the MZX axis ranges. The 3DS uses values in // (roughly) the -150 to 150 range, but MZX uses the full range of a int16_t. // The 3DS Y axis is also inverted from the typical axis direction, but that // is fixed in check_circle below. static inline int16_t axis_convert(s16 value) { int new_value = ((int)value) * 32768 / 150; return (int16_t)CLAMP(new_value, -32768, 32767); } static inline boolean check_circle(struct buffered_status *status, circlePosition *current, circlePosition *prev, int axis_x, int axis_y) { boolean rval = false; if(current->dx != prev->dx) { joystick_axis_update(status, 0, axis_x, axis_convert(current->dx)); rval = true; } if(current->dy != prev->dy) { // 3DS has an inverted Y axis on the circle pad vs. most controllers. joystick_axis_update(status, 0, axis_y, axis_convert(-current->dy)); rval = true; } return rval; } static inline boolean check_hat(struct buffered_status *status, uint32_t down, uint32_t up, uint32_t key, enum joystick_hat dir) { if(down & key) { joystick_hat_update(status, 0, dir, true); return true; } else if(up & key) { joystick_hat_update(status, 0, dir, false); return true; } return false; } static inline boolean check_joy(struct buffered_status *status, uint32_t down, uint32_t up, uint32_t key, int button) { if(down & key) { joystick_button_press(status, 0, button); return true; } else if(up & key) { joystick_button_release(status, 0, button); return true; } return false; } static inline boolean ctr_is_mouse_area(touchPosition *touch) { int mx, my; if(b_mode == BOTTOM_SCREEN_MODE_KEYBOARD) { mx = touch->px * 4 - 320; my = touch->py * 4 - (13 * 4); if(mx < 0 || mx >= 640 || my < 0 || my >= 350) return false; else return true; } else { return true; } } static inline boolean ctr_update_touch(struct buffered_status *status, touchPosition *touch) { int mx, my; if(b_mode == BOTTOM_SCREEN_MODE_KEYBOARD) { mx = touch->px * 4 - 320; my = touch->py * 4 - (13 * 4); if(mx < 0 || mx >= 640 || my < 0 || my >= 350) return false; } else { int s_height = ctr_get_subscreen_height(); mx = touch->px * 2; my = ((int)(touch->py - ((240 - s_height) / 2)) * 350 / s_height); if(mx < 0) mx = 0; if(mx >= 640) mx = 639; if(my < 0) my = 0; if(my >= 350) my = 349; } if(mx != status->mouse_pixel_x || my != status->mouse_pixel_y) { status->mouse_pixel_x = mx; status->mouse_pixel_y = my; status->mouse_x = mx / 8; status->mouse_y = my / 14; status->mouse_moved = true; allow_focus_changes = FOCUS_PASS; focus_pixel(mx, my); allow_focus_changes = FOCUS_FORBID; return true; } else { return false; } } static inline boolean ctr_update_cstick(struct buffered_status *status) { circlePosition pos; int dmx, dmy, nmx, nmy; hidCstickRead(&pos); dmx = pos.dx / 3; dmy = pos.dy / 3; if(dmx != 0 || dmy != 0) { nmx = status->mouse_pixel_x + dmx; nmy = status->mouse_pixel_y + dmy; if(nmx < 0) nmx = 0; if(nmx >= 640) nmx = 639; if(nmy < 0) nmy = 0; if(nmy >= 350) nmy = 349; if(nmx != status->mouse_pixel_x || nmy != status->mouse_pixel_y) { status->mouse_pixel_x = nmx; status->mouse_pixel_y = nmy; status->mouse_x = nmx / 8; status->mouse_y = nmy / 14; status->mouse_moved = true; focus_pixel(nmx, nmy); return true; } } return false; } boolean update_hid(void) { struct buffered_status *status = store_status(); uint32_t down, held, up; boolean retval = false; touchPosition touch; circlePosition cpad; static circlePosition last_cpad; hidScanInput(); hidCircleRead(&cpad); down = hidKeysDown(); held = hidKeysHeld(); up = hidKeysUp(); retval |= check_circle(status, &cpad, &last_cpad, 0, 1); retval |= check_hat(status, down, up, KEY_DUP, JOYHAT_UP); retval |= check_hat(status, down, up, KEY_DDOWN, JOYHAT_DOWN); retval |= check_hat(status, down, up, KEY_DLEFT, JOYHAT_LEFT); retval |= check_hat(status, down, up, KEY_DRIGHT, JOYHAT_RIGHT); retval |= check_joy(status, down, up, KEY_A, 0); retval |= check_joy(status, down, up, KEY_B, 1); retval |= check_joy(status, down, up, KEY_X, 2); retval |= check_joy(status, down, up, KEY_Y, 3); retval |= check_joy(status, down, up, KEY_L, 4); retval |= check_joy(status, down, up, KEY_R, 5); retval |= check_joy(status, down, up, KEY_SELECT, 6); retval |= check_joy(status, down, up, KEY_START, 7); retval |= check_joy(status, down, up, KEY_ZL, 8); retval |= check_joy(status, down, up, KEY_ZR, 9); last_cpad = cpad; if((down | held | up) & KEY_TOUCH) { hidTouchRead(&touch); if((down & KEY_TOUCH) && ctr_is_mouse_area(&touch)) { status->mouse_button = MOUSE_BUTTON_LEFT; status->mouse_repeat = MOUSE_BUTTON_LEFT; status->mouse_button_state |= MOUSE_BUTTON(MOUSE_BUTTON_LEFT); status->mouse_repeat_state = 1; status->mouse_drag_state = -1; status->mouse_time = get_ticks(); is_dragging = true; allow_focus_changes = FOCUS_FORBID; retval = true; } if(is_dragging) { if(up & KEY_TOUCH) { status->mouse_button_state &= ~MOUSE_BUTTON(MOUSE_BUTTON_LEFT); status->mouse_repeat = 0; status->mouse_repeat_state = 0; status->mouse_drag_state = -0; allow_focus_changes = FOCUS_ALLOW; is_dragging = false; retval = true; } else { retval |= ctr_update_touch(status, &touch); } } retval |= ctr_keyboard_update(status); } // retval |= ctr_update_cstick(status); return retval; } int ctr_get_subscreen_height(void) { switch(get_config()->video_ratio) { case RATIO_CLASSIC_4_3: case RATIO_STRETCH: return 240; default: return 175; } } boolean platform_has_screen_keyboard(void) { return true; } boolean platform_show_screen_keyboard(void) { input.showing_screen_keyboard = true; b_mode = BOTTOM_SCREEN_MODE_KEYBOARD; return true; } boolean platform_hide_screen_keyboard(void) { input.showing_screen_keyboard = false; b_mode = BOTTOM_SCREEN_MODE_PREVIEW; return true; } boolean platform_is_screen_keyboard_active(void) { return input.showing_screen_keyboard; } void platform_init_event(void) { struct buffered_status *status = store_status(); joystick_set_active(status, 0, true); joystick_map_fallback_keyboard_button(0, 5); } ================================================ FILE: arch/3ds/event.h ================================================ /* MegaZeux * * Copyright (C) 2004-2006 Gilead Kutnick * Copyright (C) 2007 Alistair John Strachan * Copyright (C) 2007 Alan Williams * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __3DS_EVENT_H__ #define __3DS_EVENT_H__ #include "../../src/event.h" __M_BEGIN_DECLS enum bottom_screen_mode { BOTTOM_SCREEN_MODE_PREVIEW, BOTTOM_SCREEN_MODE_KEYBOARD, BOTTOM_SCREEN_MODE_MAX }; enum focus_mode { FOCUS_FORBID, FOCUS_ALLOW, // checks if position changed FOCUS_PASS // ignores all checks and check updates - for touchscreen }; enum bottom_screen_mode get_bottom_screen_mode(void); enum focus_mode get_allow_focus_changes(void); int ctr_get_subscreen_height(void); __M_END_DECLS #endif /* __3DS_EVENT_H__ */ ================================================ FILE: arch/3ds/keyboard.c ================================================ /* MegaZeux * * Copyright (C) 2004-2006 Gilead Kutnick * Copyright (C) 2007 Alistair John Strachan * Copyright (C) 2007 Alan Williams * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "../../src/event.h" #include "../../src/util.h" #include <3ds.h> #include #include "event.h" #include "keyboard.h" #include "platform.h" #include "render.h" #define MAX_KEYS_DOWN 8 C3D_Tex *keyboard_tex; static enum keycode keys_down[] = { IKEY_UNKNOWN, IKEY_UNKNOWN, IKEY_UNKNOWN, IKEY_UNKNOWN, IKEY_UNKNOWN, IKEY_UNKNOWN, IKEY_UNKNOWN, IKEY_UNKNOWN }; static u8 keys_down_count = 0; static boolean force_zoom_out = false; static touch_area_t touch_areas[] = { { 2, 118, 22, 16, IKEY_ESCAPE, 0 }, { 23, 118, 22, 16, IKEY_F1, 0 }, { 44, 118, 22, 16, IKEY_F2, 0 }, { 65, 118, 22, 16, IKEY_F3, 0 }, { 86, 118, 22, 16, IKEY_F4, 0 }, { 107, 118, 22, 16, IKEY_F5, 0 }, { 128, 118, 22, 16, IKEY_F6, 0 }, { 149, 118, 22, 16, IKEY_F7, 0 }, { 170, 118, 22, 16, IKEY_F8, 0 }, { 191, 118, 22, 16, IKEY_F9, 0 }, { 212, 118, 22, 16, IKEY_F10, 0 }, { 233, 118, 22, 16, IKEY_F11, 0 }, { 254, 118, 22, 16, IKEY_F12, 0 }, { 275, 118, 22, 16, IKEY_INSERT, 0 }, { 296, 118, 22, 16, IKEY_DELETE, 0 }, { 2, 133, 22, 22, IKEY_BACKQUOTE, 0 }, { 23, 133, 22, 22, IKEY_1, 0 }, { 44, 133, 22, 22, IKEY_2, 0 }, { 65, 133, 22, 22, IKEY_3, 0 }, { 86, 133, 22, 22, IKEY_4, 0 }, { 107, 133, 22, 22, IKEY_5, 0 }, { 128, 133, 22, 22, IKEY_6, 0 }, { 149, 133, 22, 22, IKEY_7, 0 }, { 170, 133, 22, 22, IKEY_8, 0 }, { 191, 133, 22, 22, IKEY_9, 0 }, { 212, 133, 22, 22, IKEY_0, 0 }, { 233, 133, 22, 22, IKEY_MINUS, 0 }, { 254, 133, 22, 22, IKEY_EQUALS, 0 }, { 275, 133, 43, 22, IKEY_BACKSPACE, 0 }, { 2, 154, 34, 22, IKEY_TAB, 0 }, { 35, 154, 22, 22, IKEY_q, 0 }, { 56, 154, 22, 22, IKEY_w, 0 }, { 77, 154, 22, 22, IKEY_e, 0 }, { 98, 154, 22, 22, IKEY_r, 0 }, { 119, 154, 22, 22, IKEY_t, 0 }, { 140, 154, 22, 22, IKEY_y, 0 }, { 161, 154, 22, 22, IKEY_u, 0 }, { 182, 154, 22, 22, IKEY_i, 0 }, { 203, 154, 22, 22, IKEY_o, 0 }, { 224, 154, 22, 22, IKEY_p, 0 }, { 245, 154, 22, 22, IKEY_LEFTBRACKET, 0 }, { 266, 154, 22, 22, IKEY_RIGHTBRACKET, 0 }, { 287, 154, 31, 22, IKEY_BACKSLASH, 0 }, { 2, 175, 41, 22, IKEY_LCTRL, 0 }, { 42, 175, 22, 22, IKEY_a, 0 }, { 63, 175, 22, 22, IKEY_s, 0 }, { 84, 175, 22, 22, IKEY_d, 0 }, { 105, 175, 22, 22, IKEY_f, 0 }, { 126, 175, 22, 22, IKEY_g, 0 }, { 147, 175, 22, 22, IKEY_h, 0 }, { 168, 175, 22, 22, IKEY_j, 0 }, { 189, 175, 22, 22, IKEY_k, 0 }, { 210, 175, 22, 22, IKEY_l, 0 }, { 231, 175, 22, 22, IKEY_SEMICOLON, 0 }, { 252, 175, 22, 22, IKEY_QUOTE, 0 }, { 273, 175, 45, 22, IKEY_RETURN, 0 }, { 2, 196, 54, 22, IKEY_LSHIFT, 0 }, { 55, 196, 22, 22, IKEY_z, 0 }, { 76, 196, 22, 22, IKEY_x, 0 }, { 97, 196, 22, 22, IKEY_c, 0 }, { 118, 196, 22, 22, IKEY_v, 0 }, { 139, 196, 22, 22, IKEY_b, 0 }, { 160, 196, 22, 22, IKEY_n, 0 }, { 181, 196, 22, 22, IKEY_m, 0 }, { 202, 196, 22, 22, IKEY_COMMA, 0 }, { 223, 196, 22, 22, IKEY_PERIOD, 0 }, { 244, 196, 22, 22, IKEY_SLASH, 0 }, { 265, 196, 53, 22, IKEY_RSHIFT, 0 }, { 29, 217, 37, 22, IKEY_LALT, 0 }, { 65, 217, 190, 22, IKEY_SPACE, 0 }, { 254, 217, 37, 22, IKEY_RALT, 0 } }; #define touch_areas_len (sizeof(touch_areas) / sizeof(touch_area_t)) static inline boolean ctr_is_modifier(enum keycode keycode) { return keycode >= IKEY_RSHIFT && keycode <= IKEY_RSUPER; } static inline boolean ctr_key_touched(touchPosition *pos, touch_area_t *area) { return (pos->px >= area->x) && (pos->py >= area->y) && (pos->px < (area->x + area->w)) && (pos->py < (area->y + area->h)); } boolean ctr_keyboard_force_zoom_out(void) { return force_zoom_out; } void ctr_keyboard_init(struct ctr_render_data *render_data) { keyboard_tex = ctr_load_png("romfs:/kbd_display.png"); } void ctr_keyboard_draw(struct ctr_render_data *render_data) { size_t i, j; ctr_draw_2d_texture(render_data, keyboard_tex, 0, 0, 320, 240, 0, 0, 320, 240, 4.0f, 0xffffffff, false); if(ctr_is_2d()) { ctr_draw_2d_texture(render_data, keyboard_tex, force_zoom_out ? 16 : 0, 240, 16, 16, 302, 2, 16, 16, 3.0f, 0xffffffff, false); } if(ctr_supports_wide()) { ctr_draw_2d_texture(render_data, keyboard_tex, gfxIsWide() ? 48 : 32, 240, 16, 16, 284, 2, 16, 16, 3.0f, 0xffffffff, false); } if(keys_down_count > 0) { for(i = 0; i < touch_areas_len; i++) { touch_area_t *area = &touch_areas[i]; for(j = 0; j < keys_down_count; j++) { if(keys_down[j] == area->keycode) { ctr_draw_2d_texture(render_data, keyboard_tex, area->x, 240 - area->y - area->h, area->w, area->h, area->x, area->y + 1, area->w, area->h - 1, 3.0f, 0x808080ff, false); break; } } } } } boolean ctr_keyboard_update(struct buffered_status *status) { touchPosition pos; u32 down, up, i; boolean retval = false; u32 unicode; if(get_bottom_screen_mode() != BOTTOM_SCREEN_MODE_KEYBOARD) return retval; down = hidKeysDown(); up = hidKeysUp(); hidTouchRead(&pos); if(down & KEY_TOUCH) { if(ctr_is_2d() && pos.px >= 302 && pos.py >= 2 && pos.px < 318 && pos.py < 18) { force_zoom_out = !force_zoom_out; } else if(ctr_supports_wide() && pos.px >= 284 && pos.py >= 2 && pos.px < 300 && pos.py < 18) { ctr_request_set_wide(!gfxIsWide()); } for(i = 0; i < touch_areas_len; i++) { touch_area_t *area = &touch_areas[i]; if(ctr_key_touched(&pos, area)) { unicode = convert_internal_unicode(area->keycode, false); key_press(status, area->keycode); key_press_unicode(status, unicode, true); keys_down[keys_down_count++] = area->keycode; retval = true; break; } } } if(up & KEY_TOUCH && keys_down_count > 0 && !ctr_is_modifier(keys_down[keys_down_count - 1])) { for(; keys_down_count > 0; keys_down_count--) { key_release(status, keys_down[keys_down_count - 1]); keys_down[keys_down_count - 1] = IKEY_UNKNOWN; } retval = true; } return retval; } ================================================ FILE: arch/3ds/keyboard.h ================================================ /* MegaZeux * * Copyright (C) 2004-2006 Gilead Kutnick * Copyright (C) 2007 Alistair John Strachan * Copyright (C) 2007 Alan Williams * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __3DS_KEYBOARD_H__ #define __3DS_KEYBOARD_H__ #include "../../src/event.h" #include "render.h" __M_BEGIN_DECLS typedef struct { u16 x, y, w, h; enum keycode keycode; u8 flags; } touch_area_t; void ctr_keyboard_init(struct ctr_render_data *render_data); void ctr_keyboard_draw(struct ctr_render_data *render_data); boolean ctr_keyboard_update(struct buffered_status *status); boolean ctr_keyboard_force_zoom_out(void); __M_END_DECLS #endif /* __3DS_KEYBOARD_H__ */ ================================================ FILE: arch/3ds/pad.config ================================================ # Axis 1/2: Circle pad x/y # Hat: Directional pad # Button1: A # Button2: B # Button3: X # Button4: Y # Button5: Left shoulder # Button6: Right shoulder # Button7: Select # Button8: Start # Button9: ZL (NOTE: New 3DS only) # Button10: ZR (NOTE: New 3DS only) joy_axis_threshold = 16000 joy1hat = act_up, act_down, act_left, act_right joy1axis1 = act_l_left, act_l_right joy1axis2 = act_l_up, act_l_down joy1button1 = act_a joy1button2 = act_b joy1button3 = act_x joy1button4 = act_y joy1button5 = act_lshoulder joy1button6 = act_rshoulder joy1button7 = act_select joy1button8 = act_start joy1button9 = act_ltrigger joy1button10 = act_rtrigger joy1.axis_lx = 1 joy1.axis_ly = 2 ================================================ FILE: arch/3ds/pad.config.sdl12 ================================================ # Axis 1/2: Circle pad x/y # Hat: Directional pad # Button1: Start # Button2: A # Button3: B # Button4: X # Button5: Y # Button6: Left shoulder # Button7: Right shoulder # Button8: Select # Button9: ZL (NOTE: New 3DS only) # Button10: ZR (NOTE: New 3DS only) joy1hat = act_up, act_down, act_left, act_right joy1axis1 = act_l_left, act_l_right joy1axis2 = act_l_up, act_l_down joy1button1 = act_start joy1button2 = act_a joy1button3 = act_b joy1button4 = act_x joy1button5 = act_y joy1button6 = act_lshoulder joy1button7 = act_rshoulder joy1button8 = act_select joy1button9 = act_ltrigger joy1button10 = act_rtrigger joy1.axis_lx = 1 joy1.axis_ly = 2 ================================================ FILE: arch/3ds/pad.config.sdl2 ================================================ # Axis 1/2: Circle pad x/y # Button1: A # Button2: B # Button3: Select # Button4: Start # Button5: Right # Button6: Left # Button7: Up # Button8: Down # Button9: Right shoulder # Button10: Left shoulder # Button11: X # Button12: Y # Button15: ZL (NOTE: New 3DS only) # Button16: ZR (NOTE: New 3DS only) joy1axis1 = act_l_left, act_l_right joy1axis2 = act_l_up, act_l_down joy1button1 = act_a joy1button2 = act_b joy1button3 = act_select joy1button4 = act_start joy1button5 = act_right joy1button6 = act_left joy1button7 = act_up joy1button8 = act_down joy1button9 = act_rshoulder joy1button10 = act_lshoulder joy1button11 = act_x joy1button12 = act_y joy1button15 = act_ltrigger joy1button16 = act_rtrigger joy1.axis_lx = 1 joy1.axis_ly = 2 ================================================ FILE: arch/3ds/platform.c ================================================ /* MegaZeux * * Copyright (C) 2009 Alistair John Strachan * Copyright (C) 2007-2009 Kevin Vance * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "platform.h" #include "../../src/platform.h" #undef main #include "../../src/util.h" #include "../../src/event.h" #include "../../src/error.h" #include "../../src/graphics.h" #include #include #include <3ds.h> #include #include "keyboard.h" static u8 isNot2DS, consoleModelId; FILE *popen(const char *command, const char *type) { return NULL; } int pclose(FILE *stream) { return 0; } void delay(uint32_t ms) { if(ms > 0) { svcSleepThread(1e6 * ms); } } boolean ctr_is_2d(void) { return isNot2DS == 0; } boolean ctr_supports_wide(void) { return consoleModelId != 3 /* O2DS */; } uint64_t get_ticks(void) { return osGetTime(); } boolean platform_init(void) { cfguInit(); romfsInit(); osSetSpeedupEnable(1); APT_SetAppCpuTimeLimit(30); gfxInitDefault(); gfxSet3D(false); CFGU_GetSystemModel(&consoleModelId); CFGU_GetModelNintendo2DS(&isNot2DS); return true; } void platform_quit(void) { gfxExit(); romfsExit(); cfguExit(); } #ifdef CONFIG_CHECK_ALLOC static void out_of_linear_memory_check(void *p, const char *file, int line) { char msgbuf[128]; if(!p) { snprintf(msgbuf, sizeof(msgbuf), "Out of linear memory in %s:%d", file, line); msgbuf[sizeof(msgbuf)-1] = '\0'; error(msgbuf, 2, 4, 0); } } void *check_linearAlloc(size_t size, size_t alignment, const char *file, int line) { void *result = linearMemAlign(size, alignment); out_of_linear_memory_check(result, file, line); return result; } #endif /** * argv[0] will either not exist (cia) or be the location of the 3dsx. * For the cia case we can't really do anything, so assume a SHAREDIR * startup location. */ int main(int argc, char *argv[]) { static char _argv0[] = SHAREDIR "/mzxrun.3dsx"; static char *_argv[] = { _argv0 }; if(argc < 1 || argv == NULL || argv[0] == NULL) { iprintf("argv[0]: not found.\n" "using '%s'\n" "WARNING: Use of a loader that supports argv[0] is recommended.\n", _argv0); chdir(SHAREDIR); real_main(1, _argv); } else { iprintf("argv[0]: '%s'\n", argv[0]); real_main(argc, argv); } return 0; } ================================================ FILE: arch/3ds/platform.h ================================================ /* MegaZeux * * Copyright (C) 2004-2006 Gilead Kutnick * Copyright (C) 2007 Alistair John Strachan * Copyright (C) 2007 Alan Williams * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __3DS_PLATFORM_H__ #define __3DS_PLATFORM_H__ #include "../../src/compat.h" #include #include <3ds.h> #include __M_BEGIN_DECLS boolean ctr_is_2d(void); boolean ctr_supports_wide(void); #ifdef CONFIG_CHECK_ALLOC #include #define clinearAlloc(size, alignment) \ check_linearAlloc(size, alignment, __FILE__, __LINE__) void *check_linearAlloc(size_t size, size_t alignment, const char *file, int line); #else static inline void *clinearAlloc(size_t size) { return linearAlloc(size); } #endif /* CONFIG_CHECK_ALLOC */ __M_END_DECLS #endif /* __3DS_PLATFORM_H__ */ ================================================ FILE: arch/3ds/render.cpp ================================================ /* MegaZeux * * Copyright (C) 2004-2006 Gilead Kutnick * Copyright (C) 2007 Alistair John Strachan * Copyright (C) 2007 Alan Williams * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "../../src/graphics.h" #include "../../src/pngops.h" #include "../../src/render.h" #include "../../src/renderers.h" #include "../../src/util.h" #include "event.h" #include "keyboard.h" #include "platform.h" #include "render.h" #include "shader_2d_shbin.h" #include "shader_playfield_shbin.h" //#define RDR_DEBUG struct ctr_shader_data { DVLB_s *dvlb; shaderProgram_s program; int proj_loc, offs_loc, geo_count; C3D_AttrInfo attr; }; struct ctr_layer { unsigned int w, h, mode; float z; int draw_order; boolean has_background_texture; struct v_char *foreground; C3D_Tex background; }; struct v_char { s16 x, y; u32 uv; u32 col; }; struct vertex { float x, y, w, h; float z; float tx, ty, tw, th; u32 color; }; struct linear_ptr_list_entry { void *ptr; struct linear_ptr_list_entry *next; }; #define CTR_TOP_WIDTH (gfxIsWide() ? 800 : 400) #define CTR_TOP_HEIGHT 240 #define CTR_CHAR_H 16 #define CTR_TEXTURE_WIDTH 1024 #define CTR_TEXTURE_CHARS_ROW (CTR_TEXTURE_WIDTH / CHAR_W) #define CTR_TEXTURE_HEIGHT ((FULL_CHARSET_SIZE / CTR_TEXTURE_CHARS_ROW) * CTR_CHAR_H) #define CTR_LAYER_MAX (LAYER_DRAWORDER_MAX + 101) #define CTR_LAYER_CURSOR (LAYER_DRAWORDER_MAX + 50) #define CTR_LAYER_MOUSE (LAYER_DRAWORDER_MAX + 75) struct ctr_render_data { C3D_Tex charset[5], charset_vram[5]; u8 charset_dirty_set; u8 charset_dirty[NUM_CHARSETS * 2]; boolean rendering_frame, checked_frame; struct ctr_shader_data shader_2d, shader_playfield; C3D_Mtx projection; C3D_Tex playfield_tex; C3D_TexEnv env_normal, env_no_texture, env_playfield, env_playfield_inv; C3D_RenderTarget *playfield, *target_top, *target_bottom; u8 cursor_on, mouse_on; u32 last_focus_x, last_focus_y; u32 focus_x, focus_y; u32 layer_num; }; static u8 morton_lut[64] = { 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, 0x02, 0x03, 0x06, 0x07, 0x12, 0x13, 0x16, 0x17, 0x08, 0x09, 0x0c, 0x0d, 0x18, 0x19, 0x1c, 0x1d, 0x0a, 0x0b, 0x0e, 0x0f, 0x1a, 0x1b, 0x1e, 0x1f, 0x20, 0x21, 0x24, 0x25, 0x30, 0x31, 0x34, 0x35, 0x22, 0x23, 0x26, 0x27, 0x32, 0x33, 0x36, 0x37, 0x28, 0x29, 0x2c, 0x2d, 0x38, 0x39, 0x3c, 0x3d, 0x2a, 0x2b, 0x2e, 0x2f, 0x3a, 0x3b, 0x3e, 0x3f }; static u8 morton_lut4[32] = { 0x00, 0x02, 0x08, 0x0a, 0x01, 0x03, 0x09, 0x0b, 0x04, 0x06, 0x0c, 0x0e, 0x05, 0x07, 0x0d, 0x0f, 0x10, 0x12, 0x18, 0x1a, 0x11, 0x13, 0x19, 0x1b, 0x14, 0x16, 0x1c, 0x1e, 0x15, 0x17, 0x1d, 0x1f }; // 2 char bits -> 8 texture bits static u8 bitmask_mzx[4] = { 0x00, 0xf0, 0x0f, 0xff }; // 4 char bits -> 8 texture bits // bitmask_smzx[layer, 0-3][bits] static u8 bitmask_smzx[4][16] = { { 0xff, 0x0f, 0x0f, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00 }, { 0x00, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0x0f, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00 }, { 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0f, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0x00 }, { 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x0f, 0x0f, 0xff } }; // texture PNG dimensions must be powers of two static boolean tex_w_h_constraint(png_uint_32 w, png_uint_32 h) { return w > 0 && h > 0 && ((w & (w - 1)) == 0) && ((h & (h - 1)) == 0); } static inline int to_texture_size(int v) { int i; for(i = 8; i <= 65536; i *= 2) if(i >= v) return i; return v; } static void *tex_alloc_png_surface(png_uint_32 w, png_uint_32 h, png_uint_32 *stride, void **pixels) { C3D_Tex *tex; tex = (C3D_Tex *) ccalloc(1, sizeof(C3D_Tex)); *stride = w << 2; if(!C3D_TexInit(tex, w, h, GPU_RGBA8)) { free(tex); return NULL; } *pixels = tex->data; return tex; } static inline void ctr_set_2d_projection(struct ctr_render_data *render_data, int width, int height, boolean tilt) { if(tilt) Mtx_OrthoTilt(&render_data->projection, 0, width, height, 0, -1.0, CTR_LAYER_MAX, true); else Mtx_Ortho(&render_data->projection, 0, width, 0, height, -1.0, CTR_LAYER_MAX, true); } static inline void ctr_set_2d_projection_screen( struct ctr_render_data *render_data, boolean top_screen) { ctr_set_2d_projection(render_data, top_screen ? 400 : 320, 240, true); } static void ctr_bind_shader(struct ctr_shader_data *shader) { C3D_BindProgram(&shader->program); C3D_SetAttrInfo(&shader->attr); } static inline void ctr_prepare_2d(struct ctr_render_data *render_data, struct vertex *array) { C3D_BufInfo *bufInfo; bufInfo = C3D_GetBufInfo(); BufInfo_Init(bufInfo); BufInfo_Add(bufInfo, array, sizeof(struct vertex), 4, 0x3210); ctr_bind_shader(&render_data->shader_2d); C3D_FVUnifMtx4x4(GPU_GEOMETRY_SHADER, render_data->shader_2d.proj_loc, &render_data->projection); } static inline void ctr_prepare_playfield(struct ctr_render_data *render_data, struct v_char *array, float xo, float yo, float z) { C3D_BufInfo *bufInfo; bufInfo = C3D_GetBufInfo(); BufInfo_Init(bufInfo); BufInfo_Add(bufInfo, array, sizeof(struct v_char), 3, 0x210); ctr_bind_shader(&render_data->shader_playfield); C3D_FVUnifMtx4x4(GPU_GEOMETRY_SHADER, render_data->shader_playfield.proj_loc, &render_data->projection); C3D_FVUnifSet(GPU_GEOMETRY_SHADER, render_data->shader_playfield.offs_loc, (float) xo, (float) yo, z, 0.0f); } C3D_Tex *ctr_load_png(const char *name) { C3D_Tex *output; u16 width, height; u32 *data, *dataBuf; int i; output = (C3D_Tex *) png_read_file(name, NULL, NULL, tex_w_h_constraint, tex_alloc_png_surface); if(output != NULL) { C3D_TexSetWrap(output, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER); data = (u32 *)output->data; dataBuf = (u32 *)clinearAlloc(output->size, 0x10); for(i = 0; i < output->size >> 2; i++) dataBuf[i] = __builtin_bswap32(data[i]); width = output->width; height = output->height; C3D_TexDelete(output); C3D_TexInitVRAM(output, width, height, GPU_RGBA8); data = (u32*) output->data; GSPGPU_FlushDataCache(dataBuf, output->size); C3D_SyncDisplayTransfer( dataBuf, GX_BUFFER_DIM(output->width, output->height), data, GX_BUFFER_DIM(output->width, output->height), (GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | GX_TRANSFER_IN_FORMAT(GPU_RGBA8) | GX_TRANSFER_OUT_FORMAT(GPU_RGBA8) | GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO)) ); linearFree(dataBuf); } return output; } static int vertex_heap_pos = 0, vertex_heap_len = 0; static struct vertex *vertex_heap; void ctr_draw_2d_texture(struct ctr_render_data *render_data, C3D_Tex *texture, int tx, int ty, int tw, int th, float x, float y, float w, float h, float z, u32 color, boolean flipy) { struct vertex *vertices; if(flipy && texture != NULL) { ty = texture->height - ty; th = -th; } if(vertex_heap_len == 0) { vertex_heap_len = 64; vertex_heap = (struct vertex *) clinearAlloc(sizeof(struct vertex) * vertex_heap_len, 0x80); } else if(vertex_heap_pos + 1 > vertex_heap_len) { struct vertex *vertex_heap_new = (struct vertex *) clinearAlloc(sizeof(struct vertex) * vertex_heap_len * 2, 0x80); memcpy(vertex_heap_new, vertex_heap, sizeof(struct vertex) * vertex_heap_len); vertex_heap_len *= 2; linearFree(vertex_heap); vertex_heap = vertex_heap_new; } vertices = &vertex_heap[vertex_heap_pos]; vertex_heap_pos++; vertices[0].x = x; vertices[0].y = y; vertices[0].w = w; vertices[0].h = h; vertices[0].z = z; vertices[0].color = color; ctr_prepare_2d(render_data, vertex_heap); if(texture != NULL) { vertices[0].tx = tx / ((float) texture->width); vertices[0].ty = ty / ((float) texture->height); vertices[0].tw = tw / ((float) texture->width); vertices[0].th = th / ((float) texture->height); C3D_SetTexEnv(0, &(render_data->env_normal)); C3D_TexBind(0, texture); } else { vertices[0].tx = tx; vertices[0].ty = ty; vertices[0].tw = tw; vertices[0].th = th; C3D_SetTexEnv(0, &(render_data->env_no_texture)); } C3D_DrawArrays(GPU_GEOMETRY_PRIM, vertex_heap_pos - 1, 1); } static void ctr_init_shader(struct ctr_shader_data *shader, const void *data, int size, int geo_count) { shader->dvlb = DVLB_ParseFile((u32 *)data, size); shader->geo_count = geo_count; shaderProgramInit(&shader->program); shaderProgramSetVsh(&shader->program, &shader->dvlb->DVLE[0]); shaderProgramSetGsh(&shader->program, &shader->dvlb->DVLE[1], geo_count); shader->proj_loc = shaderInstanceGetUniformLocation(shader->program.geometryShader, "projection"); shader->offs_loc = shaderInstanceGetUniformLocation(shader->program.geometryShader, "offset"); AttrInfo_Init(&shader->attr); } static boolean wide_requested = false, wide_new_state; void ctr_request_set_wide(bool wide) { wide_requested = true; wide_new_state = wide; } static void ctr_set_wide(struct ctr_render_data *render_data, bool wide) { gfxSetWide(wide); C3D_RenderTargetDelete(render_data->target_top); render_data->target_top = C3D_RenderTargetCreate(240, CTR_TOP_WIDTH, GPU_RB_RGB8, GPU_RB_DEPTH16); C3D_RenderTargetClear(render_data->target_top, C3D_CLEAR_ALL, 0x000000, 0); C3D_RenderTargetSetOutput(render_data->target_top, GFX_TOP, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); } static boolean ctr_init_video(struct graphics_data *graphics, struct config_info *conf) { static struct ctr_render_data render_data; unsigned int bits_per_pixel = 16; #ifdef RDR_DEBUG consoleInit(GFX_TOP, NULL); #endif memset(&render_data, 0, sizeof(struct ctr_render_data)); graphics->render_data = &render_data; gfxSet3D(false); C3D_Init(0x40000); C3D_CullFace(GPU_CULL_NONE); render_data.rendering_frame = false; render_data.checked_frame = false; if(conf->force_bpp == 32) bits_per_pixel = conf->force_bpp; // 1024x512 is the smallest power of two texture which can fit a 640x350 playfield if(bits_per_pixel == 32) C3D_TexInitVRAM(&render_data.playfield_tex, 1024, 512, GPU_RGBA8); else C3D_TexInitVRAM(&render_data.playfield_tex, 1024, 512, GPU_RGB565); C3D_TexSetFilter(&render_data.playfield_tex, GPU_LINEAR, GPU_LINEAR); render_data.playfield = C3D_RenderTargetCreateFromTex(&render_data.playfield_tex, GPU_TEXFACE_2D, 0, GPU_RB_DEPTH16); render_data.target_top = C3D_RenderTargetCreate(240, 400, GPU_RB_RGB8, GPU_RB_DEPTH16); render_data.target_bottom = C3D_RenderTargetCreate(240, 320, GPU_RB_RGB8, GPU_RB_DEPTH16); C3D_RenderTargetClear(render_data.playfield, C3D_CLEAR_ALL, 0x000000, 0); C3D_RenderTargetClear(render_data.target_top, C3D_CLEAR_ALL, 0x000000, 0); C3D_RenderTargetClear(render_data.target_bottom, C3D_CLEAR_ALL, 0x000000, 0); C3D_RenderTargetSetOutput(render_data.target_top, GFX_TOP, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); C3D_RenderTargetSetOutput(render_data.target_bottom, GFX_BOTTOM, GFX_LEFT, GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGB8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8)); ctr_init_shader(&render_data.shader_2d, shader_2d_shbin, shader_2d_shbin_size, 4); ctr_init_shader(&render_data.shader_playfield, shader_playfield_shbin, shader_playfield_shbin_size, 3); // v0 = x,y,w,h // v1 = z // v2 = tx,ty,tw,th // v3 = color AttrInfo_AddLoader(&render_data.shader_2d.attr, 0, GPU_FLOAT, 4); AttrInfo_AddLoader(&render_data.shader_2d.attr, 1, GPU_FLOAT, 1); AttrInfo_AddLoader(&render_data.shader_2d.attr, 2, GPU_FLOAT, 4); AttrInfo_AddLoader(&render_data.shader_2d.attr, 3, GPU_UNSIGNED_BYTE, 4); // v0 = position // v1 = texcoord // v2 = color AttrInfo_AddLoader(&render_data.shader_playfield.attr, 0, GPU_SHORT, 2); AttrInfo_AddLoader(&render_data.shader_playfield.attr, 1, GPU_SHORT, 2); AttrInfo_AddLoader(&render_data.shader_playfield.attr, 2, GPU_UNSIGNED_BYTE, 4); for(int i = 0; i < 5; i++) { int tex_width = CTR_TEXTURE_WIDTH; if(i > 0) tex_width /= 2; C3D_TexInit(&render_data.charset[i], tex_width, CTR_TEXTURE_HEIGHT, GPU_A4); C3D_TexSetFilter(&render_data.charset[i], GPU_NEAREST, GPU_NEAREST); C3D_TexSetWrap(&render_data.charset[i], GPU_REPEAT, GPU_REPEAT); C3D_TexInitVRAM(&render_data.charset_vram[i], tex_width, CTR_TEXTURE_HEIGHT, GPU_A4); C3D_TexSetFilter(&render_data.charset_vram[i], GPU_NEAREST, GPU_NEAREST); C3D_TexSetWrap(&render_data.charset_vram[i], GPU_REPEAT, GPU_REPEAT); } C3D_TexEnvInit(&(render_data.env_normal)); C3D_TexEnvSrc(&(render_data.env_normal), C3D_Both, GPU_TEXTURE0, (GPU_TEVSRC) 0, (GPU_TEVSRC) 0); C3D_TexEnvOpRgb(&(render_data.env_normal), (GPU_TEVOP_RGB) 0, (GPU_TEVOP_RGB) 0, (GPU_TEVOP_RGB) 0); C3D_TexEnvOpAlpha(&(render_data.env_normal), (GPU_TEVOP_A) 0, (GPU_TEVOP_A) 0, (GPU_TEVOP_A) 0); C3D_TexEnvFunc(&(render_data.env_normal), C3D_Both, GPU_MODULATE); C3D_TexEnvInit(&(render_data.env_no_texture)); C3D_TexEnvSrc(&(render_data.env_no_texture), C3D_Both, GPU_PRIMARY_COLOR, (GPU_TEVSRC) 0, (GPU_TEVSRC) 0); C3D_TexEnvOpRgb(&(render_data.env_no_texture), (GPU_TEVOP_RGB) 0, (GPU_TEVOP_RGB) 0, (GPU_TEVOP_RGB) 0); C3D_TexEnvOpAlpha(&(render_data.env_no_texture), (GPU_TEVOP_A) 0, (GPU_TEVOP_A) 0, (GPU_TEVOP_A) 0); C3D_TexEnvFunc(&(render_data.env_no_texture), C3D_Both, GPU_REPLACE); C3D_TexEnvInit(&(render_data.env_playfield)); C3D_TexEnvSrc(&(render_data.env_playfield), C3D_RGB, (GPU_TEVSRC) 0, GPU_PRIMARY_COLOR, (GPU_TEVSRC) 0); C3D_TexEnvSrc(&(render_data.env_playfield), C3D_Alpha, (GPU_TEVSRC) 0, GPU_TEXTURE0, (GPU_TEVSRC) 0); C3D_TexEnvOpRgb(&(render_data.env_playfield), (GPU_TEVOP_RGB) 0, GPU_TEVOP_RGB_SRC_ALPHA, (GPU_TEVOP_RGB) 0); C3D_TexEnvOpAlpha(&(render_data.env_playfield), (GPU_TEVOP_A) 0, GPU_TEVOP_A_SRC_ALPHA, (GPU_TEVOP_A) 0); C3D_TexEnvFunc(&(render_data.env_playfield), C3D_Both, GPU_MODULATE); C3D_TexEnvInit(&(render_data.env_playfield_inv)); C3D_TexEnvSrc(&(render_data.env_playfield_inv), C3D_RGB, (GPU_TEVSRC) 0, GPU_PRIMARY_COLOR, (GPU_TEVSRC) 0); C3D_TexEnvSrc(&(render_data.env_playfield_inv), C3D_Alpha, (GPU_TEVSRC) 0, GPU_TEXTURE0, (GPU_TEVSRC) 0); C3D_TexEnvOpRgb(&(render_data.env_playfield_inv), (GPU_TEVOP_RGB) 0, GPU_TEVOP_RGB_SRC_ALPHA, (GPU_TEVOP_RGB) 0); C3D_TexEnvOpAlpha(&(render_data.env_playfield_inv), (GPU_TEVOP_A) 0, GPU_TEVOP_A_ONE_MINUS_SRC_ALPHA, (GPU_TEVOP_A) 0); C3D_TexEnvFunc(&(render_data.env_playfield_inv), C3D_Both, GPU_MODULATE); C3D_AlphaTest(false, GPU_GREATER, 0x80); C3D_DepthTest(false, GPU_GEQUAL, GPU_WRITE_ALL); graphics->allow_resize = 0; graphics->bits_per_pixel = bits_per_pixel; graphics->resolution_width = 640; graphics->resolution_height = 350; graphics->window_width = 640; graphics->window_height = 350; ctr_keyboard_init(&render_data); return true; } static void ctr_free_video(struct graphics_data *graphics) { // TODO: more freeing! struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data; int i; for(i = 0; i < 5; i++) { C3D_TexDelete(&render_data->charset[i]); C3D_TexDelete(&render_data->charset_vram[i]); } C3D_TexDelete(&render_data->playfield_tex); C3D_RenderTargetDelete(render_data->playfield); C3D_RenderTargetDelete(render_data->target_top); C3D_RenderTargetDelete(render_data->target_bottom); C3D_Fini(); } static boolean ctr_create_window(struct graphics_data *graphics, struct video_window *window) { return true; } static void ctr_update_colors(struct graphics_data *graphics, struct rgb_color *palette, unsigned int count) { unsigned int i; for(i = 0; i < count; i++) { graphics->flat_intensity_palette[i] = (palette[i].r << 24) | (palette[i].g << 16) | (palette[i].b << 8) | 0x000000FF; } } static inline u32 ctr_get_char_texture_row(u32 chr) { return chr / CTR_TEXTURE_CHARS_ROW; } /** * This method takes a single character line "c" for character "chr" and * Y position "y" and writes it to all textures (both MZX and SMZX). */ static inline void ctr_char_line_to_texture( struct ctr_render_data *render_data, u8 c, u32 chr, int y) { u8 *p0, *p1, *p2, *p3; u8 ch_low, ch_high; u32 offset = ((chr%CTR_TEXTURE_CHARS_ROW) * (8 * 8 / 2)); u32 offset_smzx = (((chr & (~1)) % CTR_TEXTURE_CHARS_ROW) * (4 * 8 / 2)); offset += (chr/CTR_TEXTURE_CHARS_ROW) * (CTR_TEXTURE_WIDTH * CTR_CHAR_H / 2); offset_smzx += (chr/CTR_TEXTURE_CHARS_ROW) * (CTR_TEXTURE_WIDTH/2 * CTR_CHAR_H / 2); // Add the Y position to the offsets, taking into account the 8x8 swizzling offset += ((y / 8) * (CTR_TEXTURE_WIDTH * 8 / 2)); offset += morton_lut4[(y & 7) * 4]; offset_smzx += ((y / 8) * (CTR_TEXTURE_WIDTH / 2 * 8 / 2)); offset_smzx += morton_lut4[(y & 7) * 4]; if(chr & 1) offset_smzx += 8; // Write line to MZX texture, taking into account the swizzling p0 = ((u8*) render_data->charset[0].data) + offset; p0[0] = bitmask_mzx[(c >> 6) ]; p0[2] = bitmask_mzx[(c >> 4) & 0x03]; p0[8] = bitmask_mzx[(c >> 2) & 0x03]; p0[10] = bitmask_mzx[(c ) & 0x03]; // Write line to SMZX texture, taking into account the swizzling p0 = ((u8*) render_data->charset[1].data) + offset_smzx; p1 = ((u8*) render_data->charset[2].data) + offset_smzx; p2 = ((u8*) render_data->charset[3].data) + offset_smzx; p3 = ((u8*) render_data->charset[4].data) + offset_smzx; ch_high = (c >> 4); ch_low = (c & 15); p0[0] = bitmask_smzx[0][ch_high]; p0[2] = bitmask_smzx[0][ch_low]; p1[0] = bitmask_smzx[1][ch_high]; p1[2] = bitmask_smzx[1][ch_low]; p2[0] = bitmask_smzx[2][ch_high]; p2[2] = bitmask_smzx[2][ch_low]; p3[0] = bitmask_smzx[3][ch_high]; p3[2] = bitmask_smzx[3][ch_low]; } static void ctr_remap_char_range(struct graphics_data *graphics, uint16_t first, uint16_t count) { struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data; u16 end = first + count; u8 *charset_pos; u32 i, j; if(end > FULL_CHARSET_SIZE) end = FULL_CHARSET_SIZE; charset_pos = graphics->charset; charset_pos += first * CHAR_SIZE; for(i = first; i < end; i++) { for(j = 0; j < 14; j++, charset_pos++) ctr_char_line_to_texture(render_data, *charset_pos, i, j); } first = ctr_get_char_texture_row(first); end = ctr_get_char_texture_row(end - 1); for(i = first; i <= end; i++) render_data->charset_dirty[i] = 1; render_data->charset_dirty_set = 1; } static void ctr_remap_char(struct graphics_data *graphics, uint16_t chr) { struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data; u16 tex_row = ctr_get_char_texture_row(chr); u8 *charset_pos; u32 i; charset_pos = graphics->charset; charset_pos += chr * CHAR_SIZE; for(i = 0; i < 14; i++, charset_pos++) ctr_char_line_to_texture(render_data, *charset_pos, chr, i); render_data->charset_dirty[tex_row] = 1; render_data->charset_dirty_set = 1; } static void ctr_remap_charbyte(struct graphics_data *graphics, uint16_t chr, uint8_t byte) { struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data; u16 tex_row = ctr_get_char_texture_row(chr); u8 *charset_pos; charset_pos = graphics->charset; charset_pos += chr * CHAR_SIZE + byte; ctr_char_line_to_texture(render_data, *charset_pos, chr, byte); render_data->charset_dirty[tex_row] = 1; render_data->charset_dirty_set = 1; } static inline void ctr_refresh_charsets(struct ctr_render_data *render_data, int from, int to) { u8 *charset_dirty; int coffs = 0; int csize = 0; int cincr = (CTR_TEXTURE_WIDTH * CTR_CHAR_H) / 2; int last_dirty = 0; int i; if(!render_data->charset_dirty_set) return; render_data->charset_dirty_set = 0; charset_dirty = render_data->charset_dirty; for(i = 0; i < NUM_CHARSETS * 2; i++) { if(charset_dirty[i]) { coffs = cincr * i; break; } } for(; i < NUM_CHARSETS * 2; i++) { if(charset_dirty[i]) { charset_dirty[i] = 0; last_dirty = i; } } csize = (last_dirty + 1) * cincr - coffs; if(csize <= 0) return; for(i = from; i < to; i++) { if(i != 0) { GSPGPU_FlushDataCache((u8*)(render_data->charset[i].data) + coffs/2, csize/2); C3D_SyncTextureCopy((u32*)((u8*)(render_data->charset[i].data) + coffs/2), 0, (u32*)((u8*)(render_data->charset_vram[i].data) + coffs/2), 0, csize/2, 8); } else { GSPGPU_FlushDataCache((u8*)(render_data->charset[0].data) + coffs, csize); C3D_SyncTextureCopy((u32*)((u8*)(render_data->charset[0].data) + coffs), 0, (u32*)((u8*)(render_data->charset_vram[0].data) + coffs), 0, csize, 8); } } return; } static boolean ctr_should_render(struct ctr_render_data *render_data) { if(!render_data->rendering_frame) { // If we aren't currently in control of the GPU, do not draw video. if(!gspHasGpuRight()) return false; if(wide_requested) { ctr_set_wide(render_data, wide_new_state); wide_requested = false; } if(render_data->checked_frame || !C3D_FrameBegin(C3D_FRAME_NONBLOCK)) { render_data->checked_frame = true; return false; } ctr_refresh_charsets(render_data, 0, 5); render_data->rendering_frame = true; render_data->layer_num = 0; vertex_heap_pos = 0; C3D_FrameDrawOn(render_data->playfield); ctr_set_2d_projection(render_data, 1024, 512, false); } return true; } static inline u32 ctr_char_texture_uv(u32 ch) { u16 u = (ch % CTR_TEXTURE_CHARS_ROW) * CHAR_W; u16 v = CTR_TEXTURE_HEIGHT - ((ch / CTR_TEXTURE_CHARS_ROW) * CTR_CHAR_H); return (v << 16) | u; } template static void ctr_render_layer_inner(struct graphics_data *graphics, struct video_layer *vlayer, u32 bufsize) { struct ctr_layer *layer = (struct ctr_layer *)vlayer->platform_layer_data; struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data; // Flags - dynamically set by the layer generation code. boolean draw_background_texture = HAS_BACKGROUND_TEXTURE; boolean has_content = false; // Cached variables. u32 transparent_col = vlayer->transparent_col; int offset = vlayer->offset; u32 protected_pal_position = graphics->protected_pal_position; // Temporary variables for layer generation. struct char_element *src = vlayer->data; u32 ix, iy; int pos0, pos1, pos2, pos3; int pos_bg; u32 ch, uv; u32 col0, col1, col2, col3; // SMZX = layer->mode == 0 // HAS_BACKGROUND_TEXTURE = draw_background_texture pos0 = 0; pos1 = layer->w * layer->h; if(SMZX) { pos2 = pos1 * 2; pos3 = pos1 * 3; } for(iy = 0; iy < layer->h; iy++) { for(ix = 0; ix < layer->w; ix++, src++) { if(HAS_BACKGROUND_TEXTURE) { pos_bg = morton_lut[(ix & 7) + ((iy & 7) << 3)] + ((ix & (~7)) << 3) + ((iy & (~7)) * layer->background.width); } ch = src->char_value; if(ch == INVISIBLE_CHAR) { if(HAS_BACKGROUND_TEXTURE) ((u32*) layer->background.data)[pos_bg] = 0; layer->foreground[pos0++].col = 0; layer->foreground[pos1++].col = 0; if(SMZX) { layer->foreground[pos2++].col = 0; layer->foreground[pos3++].col = 0; } continue; } has_content = true; if(ch >= 0x100) ch = (ch & 0xFF) + PROTECTED_CHARSET_POSITION; else ch = (ch + offset) % PROTECTED_CHARSET_POSITION; uv = ctr_char_texture_uv(ch); if(!SMZX) { col0 = src->bg_color; if(HAS_TRANSPARENT_COL && col0 == transparent_col) { col0 = 0; } else { if(col0 >= 16) col0 = (col0 & 0xF) + protected_pal_position; col0 = graphics->flat_intensity_palette[col0]; } col1 = src->fg_color; if(HAS_TRANSPARENT_COL && col1 == transparent_col) { col1 = 0; draw_background_texture = false; } else { if(col1 >= 16) col1 = (col1 & 0xF) + protected_pal_position; col1 = graphics->flat_intensity_palette[col1]; } if(HAS_BACKGROUND_TEXTURE) ((u32*) layer->background.data)[pos_bg] = col0; layer->foreground[pos0].uv = uv; layer->foreground[pos0++].col = col0; layer->foreground[pos1].uv = uv; layer->foreground[pos1++].col = col1; } else { u32 idx = ((src->bg_color << 6) | (src->fg_color << 2)); u32 idx0 = graphics->smzx_indices[idx ]; u32 idx1 = graphics->smzx_indices[idx + 1]; u32 idx2 = graphics->smzx_indices[idx + 2]; u32 idx3 = graphics->smzx_indices[idx + 3]; col0 = idx0 == transparent_col ? 0 : graphics->flat_intensity_palette[(u8) idx0]; col1 = idx1 == transparent_col ? 0 : graphics->flat_intensity_palette[(u8) idx1]; col2 = idx2 == transparent_col ? 0 : graphics->flat_intensity_palette[(u8) idx2]; col3 = idx3 == transparent_col ? 0 : graphics->flat_intensity_palette[(u8) idx3]; if((col1 & col2 & col3) == 0) draw_background_texture = false; if(HAS_BACKGROUND_TEXTURE) ((u32*) layer->background.data)[pos_bg] = col0; layer->foreground[pos0].uv = uv; layer->foreground[pos0++].col = col0; layer->foreground[pos1].uv = uv; layer->foreground[pos1++].col = col1; layer->foreground[pos2].uv = uv; layer->foreground[pos2++].col = col2; layer->foreground[pos3].uv = uv; layer->foreground[pos3++].col = col3; } } } if(!has_content) return; if(draw_background_texture) { C3D_TexFlush(&layer->background); ctr_draw_2d_texture(render_data, &layer->background, 0, layer->background.height - layer->h, layer->w, layer->h, vlayer->x, vlayer->y, layer->w * 8, layer->h * 14, (LAYER_DRAWORDER_MAX - layer->draw_order) + 0.66f, 0xffffffff, false); } ctr_prepare_playfield(render_data, layer->foreground, vlayer->x, vlayer->y, layer->z); GSPGPU_FlushDataCache(layer->foreground, sizeof(struct v_char) * bufsize); if(!SMZX) { C3D_TexBind(0, &render_data->charset_vram[0]); if(!draw_background_texture) { C3D_SetTexEnv(0, &(render_data->env_playfield_inv)); C3D_DrawArrays(GPU_GEOMETRY_PRIM, 0, layer->w * layer->h); } C3D_SetTexEnv(0, &(render_data->env_playfield)); C3D_DrawArrays(GPU_GEOMETRY_PRIM, layer->w * layer->h, layer->w * layer->h); } else { C3D_SetTexEnv(0, &(render_data->env_playfield)); if(!draw_background_texture) { C3D_TexBind(0, &render_data->charset_vram[1]); C3D_DrawArrays(GPU_GEOMETRY_PRIM, 0, layer->w * layer->h); } C3D_TexBind(0, &render_data->charset_vram[2]); C3D_DrawArrays(GPU_GEOMETRY_PRIM, layer->w * layer->h, layer->w * layer->h); C3D_TexBind(0, &render_data->charset_vram[3]); C3D_DrawArrays(GPU_GEOMETRY_PRIM, layer->w * layer->h * 2, layer->w * layer->h); C3D_TexBind(0, &render_data->charset_vram[4]); C3D_DrawArrays(GPU_GEOMETRY_PRIM, layer->w * layer->h * 3, layer->w * layer->h); } } template static inline void ctr_render_layer_inner(struct graphics_data *graphics, struct video_layer *vlayer, u32 bufsize) { if(vlayer->transparent_col != -1) ctr_render_layer_inner(graphics, vlayer, bufsize); else ctr_render_layer_inner(graphics, vlayer, bufsize); } template static inline void ctr_render_layer_inner(struct graphics_data *graphics, struct video_layer *vlayer, u32 bufsize) { struct ctr_layer *layer = (struct ctr_layer *)vlayer->platform_layer_data; if(layer->has_background_texture) ctr_render_layer_inner(graphics, vlayer, bufsize); else ctr_render_layer_inner(graphics, vlayer, bufsize); } static inline void ctr_render_layer_inner(struct graphics_data *graphics, struct video_layer *vlayer, u32 bufsize) { struct ctr_layer *layer = (struct ctr_layer *)vlayer->platform_layer_data; if(layer->mode > 0) ctr_render_layer_inner<1>(graphics, vlayer, bufsize); else ctr_render_layer_inner<0>(graphics, vlayer, bufsize); } static void ctr_render_layer(struct graphics_data *graphics, struct video_layer *vlayer) { struct ctr_layer *layer = (struct ctr_layer *)vlayer->platform_layer_data; struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data; u32 bufsize = vlayer->w * vlayer->h * (vlayer->mode > 0 ? 4 : 2); u32 max_bufsize = vlayer->w * vlayer->h * 4; u32 i; if(!ctr_should_render(render_data)) return; if(layer != NULL && (layer->w != vlayer->w || layer->h != vlayer->h)) { linearFree(layer->foreground); if(layer->has_background_texture) C3D_TexDelete(&(layer->background)); free(layer); layer = NULL; } if(layer != NULL && (layer->draw_order != vlayer->draw_order)) { layer->draw_order = vlayer->draw_order; layer->z = (LAYER_DRAWORDER_MAX - layer->draw_order) + 0.33f; } if(layer == NULL) { layer = (struct ctr_layer *) cmalloc(sizeof(struct ctr_layer)); layer->w = vlayer->w; layer->h = vlayer->h; layer->draw_order = vlayer->draw_order; layer->z = (LAYER_DRAWORDER_MAX - layer->draw_order) + 0.33f; layer->foreground = (struct v_char *) clinearAlloc(sizeof(struct v_char) * max_bufsize, 0x80); /** * This renderer has two methods to draw char backgrounds. The quicker * method is to draw them as single pixels on a texture stretched to the * size of the layer. The slower method is to draw the layer an extra time * for the background colors. * * The former method seems to consume a vast amount of buffer space to the * point it causes crashes when too many sprites are active. Only use it for * the default layers (these are the layers most likely to benefit anyway). */ if((vlayer->draw_order == LAYER_DRAWORDER_BOARD) || (vlayer->draw_order == LAYER_DRAWORDER_OVERLAY) || (vlayer->draw_order == LAYER_DRAWORDER_GAME_UI) || (vlayer->draw_order == LAYER_DRAWORDER_UI)) { layer->has_background_texture = true; layer->background.data = NULL; C3D_TexInit(&(layer->background), to_texture_size(layer->w), to_texture_size(layer->h), GPU_RGBA8); C3D_TexSetFilter(&(layer->background), GPU_NEAREST, GPU_NEAREST); } else layer->has_background_texture = false; vlayer->platform_layer_data = layer; // Initialize the foreground data. for(i = 0; i < max_bufsize; i++) { layer->foreground[i].x = (i % layer->w); layer->foreground[i].y = ((i / layer->w) % layer->h); layer->foreground[i].uv = 0xFFFFFFFF; } } layer->mode = vlayer->mode; ctr_render_layer_inner(graphics, vlayer, bufsize); render_data->layer_num++; } static void ctr_render_cursor(struct graphics_data *graphics, unsigned int x, unsigned int y, uint16_t color, unsigned int lines, unsigned int offset) { struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data; uint32_t flatcolor = graphics->flat_intensity_palette[color]; if(ctr_should_render(render_data)) { ctr_draw_2d_texture(render_data, NULL, 0, 0, 0, 0, x * 8, y * 14 + offset, 8, lines, CTR_LAYER_CURSOR, flatcolor, false); } } static void ctr_render_mouse(struct graphics_data *graphics, unsigned int x, unsigned int y, unsigned int w, unsigned int h) { struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data; uint32_t col = 0xFFFFFFFF; if(ctr_should_render(render_data)) { C3D_AlphaBlend(GPU_BLEND_SUBTRACT, GPU_BLEND_ADD, GPU_SRC_COLOR, GPU_DST_COLOR, GPU_SRC_ALPHA, GPU_DST_ALPHA); ctr_draw_2d_texture(render_data, NULL, 0, 0, 0, 0, x, y, w, h, CTR_LAYER_MOUSE, col, false); C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA); } } static inline void ctr_draw_playfield(struct ctr_render_data *render_data, boolean top_screen) { int x, y; int width, height; float slider; ctr_set_2d_projection_screen(render_data, top_screen); if(top_screen) { if(ctr_keyboard_force_zoom_out()) { slider = 1.0f; } else { slider = (osGet3DSliderState() * 1.3f) - 0.15f; if(slider < 0.0f) slider = 0.0f; if(slider > 1.0f) slider = 1.0f; } width = 400 + (240 * slider); height = 240 + (144 * slider); x = render_data->focus_x - (width / 2); y = render_data->focus_y - (height / 2); if(x < 0) x = 0; if((x + width) > 640) x = 640 - width; if(height > 350) { ctr_draw_2d_texture(render_data, &render_data->playfield_tex, x, 512 - 350, width, 350, 0, (240 - (240 * 350 / height)) / 2, 400, 240 * 350 / height, 2.0f, 0xffffffff, true); } else { if(y < 0) y = 0; if((y + height) > 350) y = 350 - height; ctr_draw_2d_texture(render_data, &render_data->playfield_tex, x, 512 - y - height, width, height, 0, 0, 400, 240, 2.0f, 0xffffffff, true); } } else { if(get_bottom_screen_mode() == BOTTOM_SCREEN_MODE_KEYBOARD) { ctr_draw_2d_texture(render_data, &render_data->playfield_tex, 0, 512 - 350, 640, 350, 80, 12.75, 160, 87.5, 2.0f, 0xffffffff, true); } else { int width = 320, height = ctr_get_subscreen_height(); ctr_draw_2d_texture(render_data, &render_data->playfield_tex, 0, 512 - 350, 640, 350, (int) ((320 - width) / 2), (int) ((240 - height) / 2), width, height, 2.0f, 0xffffffff, true ); } } } static void ctr_sync_screen(struct graphics_data *graphics, struct video_window *window) { struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data; if(!ctr_should_render(render_data)) { render_data->checked_frame = false; return; } #ifndef RDR_DEBUG C3D_RenderTargetClear(render_data->target_top, C3D_CLEAR_ALL, 0x000000, 0); C3D_FrameDrawOn(render_data->target_top); ctr_draw_playfield(render_data, true); #endif C3D_RenderTargetClear(render_data->target_bottom, C3D_CLEAR_ALL, 0x000000, 0); C3D_FrameDrawOn(render_data->target_bottom); if(get_bottom_screen_mode() == BOTTOM_SCREEN_MODE_KEYBOARD) { ctr_set_2d_projection_screen(render_data, false); ctr_keyboard_draw(render_data); } ctr_draw_playfield(render_data, false); render_data->cursor_on = 0; render_data->mouse_on = 0; C3D_FrameEnd(0); render_data->rendering_frame = false; render_data->checked_frame = false; } static void ctr_focus_pixel(struct graphics_data *graphics, unsigned int x, unsigned int y) { struct ctr_render_data *render_data = (struct ctr_render_data *) graphics->render_data; switch(get_allow_focus_changes()) { case FOCUS_FORBID: return; case FOCUS_ALLOW: if(render_data->last_focus_x != x || render_data->last_focus_y != y) { render_data->last_focus_x = x; render_data->last_focus_y = y; render_data->focus_x = x; render_data->focus_y = y; } break; case FOCUS_PASS: render_data->focus_x = x; render_data->focus_y = y; break; } } void render_ctr_register(struct renderer *renderer) { memset(renderer, 0, sizeof(struct renderer)); renderer->init_video = ctr_init_video; renderer->free_video = ctr_free_video; renderer->create_window = ctr_create_window; renderer->set_viewport = set_window_viewport_centered; renderer->update_colors = ctr_update_colors; renderer->remap_char_range = ctr_remap_char_range; renderer->remap_char = ctr_remap_char; renderer->remap_charbyte = ctr_remap_charbyte; renderer->render_layer = ctr_render_layer; renderer->render_cursor = ctr_render_cursor; renderer->render_mouse = ctr_render_mouse; renderer->sync_screen = ctr_sync_screen; renderer->focus_pixel = ctr_focus_pixel; } ================================================ FILE: arch/3ds/render.h ================================================ /* MegaZeux * * Copyright (C) 2004-2006 Gilead Kutnick * Copyright (C) 2007 Alistair John Strachan * Copyright (C) 2007 Alan Williams * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __3DS_RENDER_H__ #define __3DS_RENDER_H__ #include #include <3ds.h> #include #include "../../src/compat.h" __M_BEGIN_DECLS struct ctr_render_data; C3D_Tex *ctr_load_png(const char *name); void ctr_draw_2d_texture(struct ctr_render_data *render_data, C3D_Tex *texture, int tx, int ty, int tw, int th, float x, float y, float w, float h, float z, u32 color, boolean flipy); void ctr_request_set_wide(bool wide); int ctr_get_subscreen_height(void); __M_END_DECLS #endif /* __3DS_RENDER_H__ */ ================================================ FILE: arch/3ds/shader_2d.g.pica ================================================ ; MegaZeux ; ; Copyright (C) 2004-2006 Gilead Kutnick ; Copyright (C) 2007 Alistair John Strachan ; Copyright (C) 2007 Alan Williams ; ; This program is free software; you can redistribute it and/or ; modify it under the terms of the GNU General Public License as ; published by the Free Software Foundation; either version 2 of ; the License, or (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ; General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .gsh point c0 .fvec projection[4] .out outpos position .out outtc0 texcoord0 .out outclr color .constf CONSTS(1.0, 0.0, 0.0, 0.0) .entry gmain .proc gmain mov r0.xy, v0.xy mov r0.z, v1.x mov r0.w, CONSTS.x mov r4.xy, v0.zw mov r8.zw, r0.zw mov r6.xy, v2.xy mov r6.zw, CONSTS.zw mov r5.xy, v2.zw mov r10.zw, r6.zw setemit 0 add r8.xy, r0.xy, r4.xy mov r10.y, r6.y add r10.x, r6.x, r5.x call emit_vertex emit setemit 1 mov r8.x, r0.x add r8.y, r0.y, r4.y mov r10, r6 call emit_vertex emit setemit 2, prim mov r8.xy, r0.xy mov r10.x, r6.x add r10.y, r6.y, r5.y call emit_vertex emit setemit 1, prim inv mov r8.y, r0.y add r8.x, r0.x, r4.x add r10.xy, r6.xy, r5.xy call emit_vertex emit end .end .proc emit_vertex dp4 outpos.x, projection[0], r8 dp4 outpos.y, projection[1], r8 dp4 outpos.z, projection[2], r8 dp4 outpos.w, projection[3], r8 mov outclr, v3 mov outtc0, r10 .end ================================================ FILE: arch/3ds/shader_2d.v.pica ================================================ ; MegaZeux ; ; Copyright (C) 2004-2006 Gilead Kutnick ; Copyright (C) 2007 Alistair John Strachan ; Copyright (C) 2007 Alan Williams ; ; This program is free software; you can redistribute it and/or ; modify it under the terms of the GNU General Public License as ; published by the Free Software Foundation; either version 2 of ; the License, or (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ; General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .constf RGBS(0.00392156862745098, 0.00392156862745098, 0.00392156862745098, 0.00392156862745098) .out - dummy o0 .out - dummy o1 .out - dummy o2 .out - dummy o3 .proc main mov o0, v0 mov o1, v1 mov o2, v2 mov r1, RGBS mul o3, v3.wzyx, r1.x end .end ================================================ FILE: arch/3ds/shader_playfield.g.pica ================================================ ; MegaZeux ; ; Copyright (C) 2004-2006 Gilead Kutnick ; Copyright (C) 2007 Alistair John Strachan ; Copyright (C) 2007 Alan Williams ; ; This program is free software; you can redistribute it and/or ; modify it under the terms of the GNU General Public License as ; published by the Free Software Foundation; either version 2 of ; the License, or (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ; General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .gsh point c0 .fvec projection[4] .fvec offset .out outpos position .out outtc0 texcoord0 .out outclr color .alias inpos v0 .alias intc0 v1 .alias inclr v2 .constf SCALES(0.0009765625, 0.001953125, -1, 1) .constf UVOFF(8, -14, 0, 0) .constf POSSCALE(8.0, 14.0, 1.0, 1.0) .entry gmain .proc gmain mov r4, POSSCALE mov r2, intc0 mov r3.xy, inpos mov r3.z, UVOFF.z mad r0, r3, r4, offset mov r11, SCALES mov r0.w, POSSCALE.w mul r5.xy, UVOFF.xy, r11.xy mul r6, r2, r11 setemit 0 add r8.xy, r0.xy, r4.xy add r10.xy, r6.xy, r5.xy call emit_vertex emit setemit 1 mov r8.y, r0.y add r8.x, r0.x, r4.x mov r10.y, r6.y add r10.x, r6.x, r5.x call emit_vertex emit setemit 2, prim mov r8, r0 mov r10, r6 call emit_vertex emit setemit 1, prim inv mov r8.x, r0.x add r8.y, r0.y, r4.y mov r10.x, r6.x add r10.y, r6.y, r5.y call emit_vertex emit end .end .proc emit_vertex dp4 outpos.x, projection[0], r8 dp4 outpos.y, projection[1], r8 dp4 outpos.z, projection[2], r8 dp4 outpos.w, projection[3], r8 mov outclr, inclr mov outtc0, r10 .end ================================================ FILE: arch/3ds/shader_playfield.v.pica ================================================ ; MegaZeux ; ; Copyright (C) 2004-2006 Gilead Kutnick ; Copyright (C) 2007 Alistair John Strachan ; Copyright (C) 2007 Alan Williams ; ; This program is free software; you can redistribute it and/or ; modify it under the terms of the GNU General Public License as ; published by the Free Software Foundation; either version 2 of ; the License, or (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ; General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .out outpos position .out outtc0 texcoord0 .out outclr color .alias inpos v0 .alias intc0 v1 .alias inclr v2 .constf RGBS(0.00392156862745098, 0.00392156862745098, 0.00392156862745098, 0.00392156862745098) .proc main mov outpos, inpos mov outtc0, intc0 mov r1, RGBS mul outclr, inclr.wzyx, r1.x end .end ================================================ FILE: arch/3ds/thread.h ================================================ /* MegaZeux * * Copyright (C) 2016, 2018 Adrian Siekierka * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __THREAD_3DS_H #define __THREAD_3DS_H #include "../../src/compat.h" #define STACK_SIZE_CTR 8096 __M_BEGIN_DECLS #include <3ds.h> #define THREAD_RES void #define THREAD_RETURN do { return; } while(0) typedef CondVar platform_cond; typedef LightLock platform_mutex; typedef LightSemaphore platform_sem; typedef Thread platform_thread; typedef Thread platform_thread_id; typedef ThreadFunc platform_thread_fn; static inline boolean platform_mutex_init(platform_mutex *mutex) { LightLock_Init(mutex); return true; } static inline boolean platform_mutex_destroy(platform_mutex *mutex) { return true; } static inline boolean platform_mutex_lock(platform_mutex *mutex) { LightLock_Lock(mutex); return true; } static inline boolean platform_mutex_unlock(platform_mutex *mutex) { LightLock_Unlock(mutex); return true; } static inline boolean platform_cond_init(platform_cond *cond) { CondVar_Init(cond); return true; } static inline boolean platform_cond_destroy(platform_cond *cond) { return true; } static inline boolean platform_cond_wait(platform_cond *cond, platform_mutex *mutex) { CondVar_Wait(cond, mutex); return true; } static inline boolean platform_cond_timedwait(platform_cond *cond, platform_mutex *mutex, unsigned int timeout_ms) { s64 timeout_ns = (s64)timeout_ms * 1000000; if(CondVar_WaitTimeout(cond, mutex, timeout_ns)) return false; return true; } static inline boolean platform_cond_signal(platform_cond *cond) { CondVar_Signal(cond); return true; } static inline boolean platform_cond_broadcast(platform_cond *cond) { CondVar_Broadcast(cond); return true; } static inline boolean platform_sem_init(platform_sem *sem, unsigned init_value) { if(init_value > INT16_MAX) return false; LightSemaphore_Init(sem, init_value, INT16_MAX); return true; } static inline boolean platform_sem_destroy(platform_sem *sem) { return true; } static inline boolean platform_sem_wait(platform_sem *sem) { LightSemaphore_Acquire(sem, 1); return true; } static inline boolean platform_sem_post(platform_sem *sem) { LightSemaphore_Release(sem, 1); return true; } static inline boolean platform_thread_create(platform_thread *thread, platform_thread_fn start_function, void *data) { Thread t; s32 priority; svcGetThreadPriority(&priority, CUR_THREAD_HANDLE); t = threadCreate(start_function, data, STACK_SIZE_CTR, priority-1, -1, true); if(t) { *thread = t; return true; } return false; } static inline boolean platform_thread_join(platform_thread *thread) { // Return value not documented... threadJoin(*thread, U64_MAX); return true; } static inline platform_thread_id platform_get_thread_id(void) { return threadGetCurrent(); } static inline boolean platform_is_same_thread(platform_thread_id a, platform_thread_id b) { return a == b; } __M_END_DECLS #endif // __THREAD_3DS_H ================================================ FILE: arch/LICENSE.3rd ================================================ ---------------------------------------------------------------- Third party software licenses for MegaZeux ---------------------------------------------------------------- The licenses here applicable to a given build of MegaZeux will vary. Typically one C standard library (glibc/Newlib/musl/etc.), one module playback library (libxmp/libmodplug/MikMod/Maxmod), SDL, and several other libraries will be linked. The ports that use each library by default will be indicated below. Not all libcs are accounted for here, but the ones most often linked by MegaZeux are. Some particularly verbose licenses are only provided as URL. For MegaZeux's license, see LICENSE. ---------------------------------------------------------------- glibc ---------------------------------------------------------------- glibc is available under the GNU Lesser General Public License 2.1. See LICENSE.LGPL2 or /usr/share/licenses/glibc for more information. Used by ports: Most Linux distributions. Home page: https://www.gnu.org/software/libc/ License URL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html ---------------------------------------------------------------- MSVCRT.DLL, WS2_32.DLL, WSOCK.DLL ---------------------------------------------------------------- These Microsoft Windows libraries are proprietary software. Linking them is permitted under the GPL system library exception. Used by ports: MinGW and MSVC. Home page: https://www.microsoft.com/ ---------------------------------------------------------------- Apple libc ---------------------------------------------------------------- Apple libc is available under the Apple Public Source License 2.0. Used by ports: Darwin and Xcode. Home page: https://opensource.apple.com/source/Libc/ License URL: https://opensource.apple.com/license/apsl/ ---------------------------------------------------------------- Newlib ---------------------------------------------------------------- Newlib is available under a collection of BSD-like licenses. See LICENSE.Newlib or for more information. Used by ports: NDS, 3DS, Wii, Wii U, Switch, PSP, PS Vita, Dreamcast, AmigaOS 4. Home page: https://sourceware.org/newlib/ License URL: https://sourceware.org/newlib/COPYING.NEWLIB ---------------------------------------------------------------- musl ---------------------------------------------------------------- musl is available under the MIT license. Used by ports: Emscripten (also the default libc on some distributions). Home page: https://musl.libc.org/ License URL: https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT Copyright © 2005-2020 Rich Felker, et al. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------------------------------------------------------- Bionic libc ---------------------------------------------------------------- Bionic is available under a collection of BSD-like licenses. Used by ports: Android. Home page: https://android.googlesource.com/platform/bionic/ License URL: https://android.googlesource.com/platform/bionic/+/master/libc/NOTICE ---------------------------------------------------------------- DJGPP libc, libm, and crt0 ---------------------------------------------------------------- DJGPP libc and crt0 are available under the GNU Lesser General Public License 2.1. DJGPP libm is *probably* available under the GNU General Public License 2.0. DJGPP also contains contributed code under various permissive licenses. See LICENSE.DJGPP, LICENSE.LGPL2, and LICENSE for more information. Used by ports: DJGPP. Home page: http://www.delorie.com/djgpp/ Source URL: http://www.delorie.com/pub/djgpp/ (djlsr205.zip) ---------------------------------------------------------------- SDL ---------------------------------------------------------------- SDL is available under the zlib license. gamecontrollerdb.txt is available under an identical license. Used by ports: Most. Home page: https://www.libsdl.org/ Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. ---------------------------------------------------------------- SDL 1.2 ---------------------------------------------------------------- SDL 1.2 is available under the GNU Lesser General Public License 2.1. See LICENSE.LGPL2 or /usr/share/licenses/SDL for more information. Used by ports: Mac OS X PowerPC, PSP, GP2X, Pandora, AmigaOS 4. Home page: https://www.libsdl.org/ License URL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html ---------------------------------------------------------------- khash ---------------------------------------------------------------- MZX uses a heavily modified khash which is available under the MIT license. Used by ports: All. Home page: https://attractivechaos.github.io/klib/ The MIT License Copyright (c) 2008, 2009, 2011 by Attractive Chaos Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------------------------------------------------------- zlib ---------------------------------------------------------------- zlib is available under the zlib license. Used by ports: All. Home page: https://zlib.net/ zlib.h -- interface of the 'zlib' general purpose compression library version 1.2.11, January 15th, 2017 Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu ---------------------------------------------------------------- libpng ---------------------------------------------------------------- libpng is available under a zlib-like license. Used by ports: Most. Home page: https://www.libpng.org/ PNG Reference Library License version 2 --------------------------------------- * Copyright (c) 1995-2019 The PNG Reference Library Authors. * Copyright (c) 2018-2019 Cosmin Truta. * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. * Copyright (c) 1996-1997 Andreas Dilger. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. The software is supplied "as is", without warranty of any kind, express or implied, including, without limitation, the warranties of merchantability, fitness for a particular purpose, title, and non-infringement. In no event shall the Copyright owners, or anyone distributing the software, be liable for any damages or other liability, whether in contract, tort or otherwise, arising from, out of, or in connection with the software, or the use or other dealings in the software, even if advised of the possibility of such damage. Permission is hereby granted to use, copy, modify, and distribute this software, or portions hereof, for any purpose, without fee, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated, but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This Copyright notice may not be removed or altered from any source or altered source distribution. ---------------------------------------------------------------- libogg, libvorbis, and Tremor ---------------------------------------------------------------- libogg, libvorbis, and Tremor are all available under the BSD-3-clause license. Used by ports: All except DJGPP, NDS. Home page: https://xiph.org/ogg/ Home page: https://xiph.org/vorbis/ Copyright (c) 2002-2020 Xiph.org Foundation Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------- stb_vorbis ---------------------------------------------------------------- stb_vorbis is available under a dual MIT/Unlicense license. MegaZeux uses a fork of stb_vorbis maintained by sezero as some of the required patches have not been merged upstream yet. Used by ports: DJGPP Home page: https://github.com/nothings/stb sezero fork: https://github.com/sezero/stb ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ---------------------------------------------------------------- libxmp ---------------------------------------------------------------- The subset of libxmp used by MegaZeux is available under the MIT license. Used by ports: All except NDS. Home page: http://xmp.sourceforge.net/ Extended Module Player Copyright (C) 1996-2021 Claudio Matsuoka and Hipolito Carraro Jr Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------------------------------------------------------- libmodplug ---------------------------------------------------------------- libmodplug is available in the public domain. Used by ports: None (non-default compile-time option). Home page: https://github.com/Konstanty/libmodplug ---------------------------------------------------------------- MikMod ---------------------------------------------------------------- libmikmod is available under the GNU Lesser General Public License 2.1. See LICENSE.LGPL2 for more information. Used by ports: None (non-default compile-time option). Home page: http://mikmod.sourceforge.net/ License URL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html ---------------------------------------------------------------- OpenMPT ---------------------------------------------------------------- libopenmpt is available under the BSD-3-clause license. Used by ports: None (non-default compile-time option). Home page: https://lib.openmpt.org/libopenmpt/ Copyright (c) 2004-2022, OpenMPT Project Developers and Contributors Copyright (c) 1997-2003, Olivier Lapicque All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the OpenMPT project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------- Reality Adlib Tracker v2 ---------------------------------------------------------------- The Reality Adlib Tracker v2 playercode is available in the public domain. Used by ports: All except NDS. Home page: https://www.3eality.com/productions/reality-adlib-tracker ---------------------------------------------------------------- Maxmod ---------------------------------------------------------------- Maxmod is available under the ISC license. Used by ports: NDS. Home page: https://maxmod.org /**************************************************************************** * __ * * ____ ___ ____ __ ______ ___ ____ ____/ / * * / __ `__ \/ __ `/ |/ / __ `__ \/ __ \/ __ / * * / / / / / / /_/ /> * * This software may be used freely so long as this copyright notice is * left intact. There is no warranty on this software. */ 4) Regents of the University of California (stdlib) /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that: (1) source distributions retain this entire copyright * notice and comment, and (2) distributions including binaries display * the following acknowledgement: ``This product includes software * developed by the University of California, Berkeley and its contributors'' * in the documentation or other materials provided with the distribution * and in all advertising materials mentioning features or use of this * software. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ 5) Regents of the University of California (ctime) /* * Copyright (c) 1987, 1989 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Arthur David Olson of the National Cancer Institute. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ 6) Martin Strömberg (libc) * Copyright (C) 2003 Martin Str@"omberg . * * This software may be used freely so long as this copyright notice is * left intact. There is no warranty on this software. 7) Eli Zaretskii (libc) * Copyright (c) 1995-98 Eli Zaretskii * * This software may be used freely so long as this copyright notice is * left intact. There is no warranty on this software. 8) Morten Welinder (libc) Copyright 1995 by Morten Welinder This file maybe freely distributed and modified as long as the copyright notice remains. 9) Borca Daniel and Andrew Zabolotny (libc) /* Copyright (C) 2003 Borca Daniel * Copyright (C) 2000 Andrew Zabolotny * Partly based on work by Charles Sandmann and DJ Delorie. * Usage of this library is not restricted in any way. * ABSOLUTELY no warranties. Contributed to the DJGPP project. */ 10) Charles Sandmann (libc) /* Copyright (C) 1995 Charles Sandmann (sandmann@clio.rice.edu) This software may be freely distributed with above copyright, no warranty. Based on code by DJ Delorie, it's really his, enhanced, bugs fixed. */ /* Copyright (C) 1994, 1995 Charles Sandmann (sandmann@clio.rice.edu) * ... * This file maybe freely distributed, no warranty. */ /* Copyright (C) 1994, 1995 Charles Sandmann (sandmann@clio.rice.edu) * This file maybe freely distributed and modified as long as copyright remains. */ /* Copyright (C) 1995 Charles Sandmann (sandmann@clio.rice.edu) This software may be freely distributed, no warranty. 11) Henry Spencer (regex) Copyright 1992, 1993, 1994, 1997 Henry Spencer. All rights reserved. This software is not subject to any license of the American Telephone and Telegraph Company or of the Regents of the University of California. Permission is granted to anyone to use this software for any purpose on any computer system, and to alter it and redistribute it, subject to the following restrictions: 1. The author is not responsible for the consequences of use of this software, no matter how awful, even if they arise from flaws in it. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. Since few users ever read sources, credits must appear in the documentation. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. Since few users ever read sources, credits must appear in the documentation. 4. This notice may not be removed or altered. 12) Eric Backus (xstat) /* (c) Copyright 1992 Eric Backus This software may be used freely so long as this copyright notice is left intact. There is no warranty on this software. */ ================================================ FILE: arch/LICENSE.LGPL2 ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ================================================ FILE: arch/LICENSE.MPL2 ================================================ Mozilla Public License Version 2.0 ================================== 1. Definitions -------------- 1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. 1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. 1.3. "Contribution" means Covered Software of a particular Contributor. 1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. 1.5. "Incompatible With Secondary Licenses" means (a) that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or (b) that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. 1.6. "Executable Form" means any form of the work other than Source Code Form. 1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" means this document. 1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. 1.10. "Modifications" means any of the following: (a) any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or (b) any new file in Source Code Form that contains any Covered Software. 1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. 1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. 1.13. "Source Code Form" means the form of the work preferred for making modifications. 1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants and Conditions -------------------------------- 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and (b) under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: (a) for any code that a Contributor has removed from Covered Software; or (b) for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or (c) under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. 3. Responsibilities ------------------- 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: (a) such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and (b) You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. 4. Inability to Comply Due to Statute or Regulation --------------------------------------------------- If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Termination -------------- 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. ************************************************************************ * * * 6. Disclaimer of Warranty * * ------------------------- * * * * Covered Software is provided under this License on an "as is" * * basis, without warranty of any kind, either expressed, implied, or * * statutory, including, without limitation, warranties that the * * Covered Software is free of defects, merchantable, fit for a * * particular purpose or non-infringing. The entire risk as to the * * quality and performance of the Covered Software is with You. * * Should any Covered Software prove defective in any respect, You * * (not any Contributor) assume the cost of any necessary servicing, * * repair, or correction. This disclaimer of warranty constitutes an * * essential part of this License. No use of any Covered Software is * * authorized under this License except under this disclaimer. * * * ************************************************************************ ************************************************************************ * * * 7. Limitation of Liability * * -------------------------- * * * * Under no circumstances and under no legal theory, whether tort * * (including negligence), contract, or otherwise, shall any * * Contributor, or anyone who distributes Covered Software as * * permitted above, be liable to You for any direct, indirect, * * special, incidental, or consequential damages of any character * * including, without limitation, damages for lost profits, loss of * * goodwill, work stoppage, computer failure or malfunction, or any * * and all other commercial damages or losses, even if such party * * shall have been informed of the possibility of such damages. This * * limitation of liability shall not apply to liability for death or * * personal injury resulting from such party's negligence to the * * extent applicable law prohibits such limitation. Some * * jurisdictions do not allow the exclusion or limitation of * * incidental or consequential damages, so this exclusion and * * limitation may not apply to You. * * * ************************************************************************ 8. Litigation ------------- Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. 9. Miscellaneous ---------------- This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. 10. Versions of the License --------------------------- 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice ------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. Exhibit B - "Incompatible With Secondary Licenses" Notice --------------------------------------------------------- This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. ================================================ FILE: arch/LICENSE.Newlib ================================================ The newlib subdirectory is a collection of software from several sources. Each file may have its own copyright/license that is embedded in the source file. Unless otherwise noted in the body of the source file(s), the following copyright notices will apply to the contents of the newlib subdirectory: (1) Red Hat Incorporated Copyright (c) 1994-2009 Red Hat, Inc. All rights reserved. This copyrighted material is made available to anyone wishing to use, modify, copy, or redistribute it subject to the terms and conditions of the BSD License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. A copy of this license is available at http://www.opensource.org/licenses. Any Red Hat trademarks that are incorporated in the source code or documentation are not subject to the BSD License and may only be used or replicated with the express permission of Red Hat, Inc. (2) University of California, Berkeley Copyright (c) 1981-2000 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (3) David M. Gay (AT&T 1991, Lucent 1998) The author of this software is David M. Gay. Copyright (c) 1991 by AT&T. Permission to use, copy, modify, and distribute this software for any purpose without fee is hereby granted, provided that this entire notice is included in all copies of any software which is or includes a copy or modification of this software and in all copies of the supporting documentation for such software. THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. ------------------------------------------------------------------- The author of this software is David M. Gay. Copyright (C) 1998-2001 by Lucent Technologies All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that the copyright notice and this permission notice and warranty disclaimer appear in supporting documentation, and that the name of Lucent or any of its entities not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (4) Advanced Micro Devices Copyright 1989, 1990 Advanced Micro Devices, Inc. This software is the property of Advanced Micro Devices, Inc (AMD) which specifically grants the user the right to modify, use and distribute this software provided this notice is not removed or altered. All other rights are reserved by AMD. AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR USE OF THIS SOFTWARE. So that all may benefit from your experience, please report any problems or suggestions about this software to the 29K Technical Support Center at 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131 in the UK, or 0031-11-1129 in Japan, toll free. The direct dial number is 512-462-4118. Advanced Micro Devices, Inc. 29K Support Products Mail Stop 573 5900 E. Ben White Blvd. Austin, TX 78741 800-292-9263 (5) (6) (7) Sun Microsystems Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. Developed at SunPro, a Sun Microsystems, Inc. business. Permission to use, copy, modify, and distribute this software is freely granted, provided that this notice is preserved. (8) Hewlett Packard (c) Copyright 1986 HEWLETT-PACKARD COMPANY To anyone who acknowledges that this file is provided "AS IS" without any express or implied warranty: permission to use, copy, modify, and distribute this file for any purpose is hereby granted without fee, provided that the above copyright notice and this notice appears in all copies, and that the name of Hewlett-Packard Company not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Hewlett-Packard Company makes no representations about the suitability of this software for any purpose. (9) Hans-Peter Nilsson Copyright (C) 2001 Hans-Peter Nilsson Permission to use, copy, modify, and distribute this software is freely granted, provided that the above copyright notice, this notice and the following disclaimer are preserved with no changes. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. (10) Stephane Carrez (m68hc11-elf/m68hc12-elf targets only) Copyright (C) 1999, 2000, 2001, 2002 Stephane Carrez (stcarrez@nerim.fr) The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. (11) Christopher G. Demetriou Copyright (c) 2001 Christopher G. Demetriou All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (12) SuperH, Inc. Copyright 2002 SuperH, Inc. All rights reserved This software is the property of SuperH, Inc (SuperH) which specifically grants the user the right to modify, use and distribute this software provided this notice is not removed or altered. All other rights are reserved by SuperH. SUPERH MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE. IN NO EVENT SHALL SUPERH BE LIABLE FOR INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR USE OF THIS SOFTWARE. So that all may benefit from your experience, please report any problems or suggestions about this software to the SuperH Support Center via e-mail at softwaresupport@superh.com . SuperH, Inc. 405 River Oaks Parkway San Jose CA 95134 USA (13) Royal Institute of Technology Copyright (c) 1999 Kungliga Tekniska Högskolan (Royal Institute of Technology, Stockholm, Sweden). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of KTH nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (14) Alexey Zelkin Copyright (c) 2000, 2001 Alexey Zelkin All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (15) Andrey A. Chernov Copyright (C) 1997 by Andrey A. Chernov, Moscow, Russia. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (16) FreeBSD Copyright (c) 1997-2002 FreeBSD Project. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (17) S. L. Moshier Author: S. L. Moshier. Copyright (c) 1984,2000 S.L. Moshier Permission to use, copy, modify, and distribute this software for any purpose without fee is hereby granted, provided that this entire notice is included in all copies of any software which is or includes a copy or modification of this software and in all copies of the supporting documentation for such software. THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. (18) Citrus Project Copyright (c)1999 Citrus Project, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (19) Todd C. Miller Copyright (c) 1998 Todd C. Miller All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (20) DJ Delorie (i386) Copyright (C) 1991 DJ Delorie All rights reserved. Redistribution, modification, and use in source and binary forms is permitted provided that the above copyright notice and following paragraph are duplicated in all such forms. This file is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. (21) Free Software Foundation LGPL License (*-linux* targets only) Copyright (C) 1990-1999, 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Mark Kettenis , 1997. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. (22) Xavier Leroy LGPL License (i[3456]86-*-linux* targets only) Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. (23) Intel (i960) Copyright (c) 1993 Intel Corporation Intel hereby grants you permission to copy, modify, and distribute this software and its documentation. Intel grants this permission provided that the above copyright notice appears in all copies and that both the copyright notice and this permission notice appear in supporting documentation. In addition, Intel grants this permission provided that you prominently mark as "not part of the original" any modifications made to this software or documentation, and that the name of Intel Corporation not be used in advertising or publicity pertaining to distribution of the software or the documentation without specific, written prior permission. Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or representations regarding the use of, or the results of the use of, the software and documentation in terms of correctness, accuracy, reliability, currentness, or otherwise; and you rely on the software, documentation and results solely at your own risk. IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER. (24) Hewlett-Packard (hppa targets only) (c) Copyright 1986 HEWLETT-PACKARD COMPANY To anyone who acknowledges that this file is provided "AS IS" without any express or implied warranty: permission to use, copy, modify, and distribute this file for any purpose is hereby granted without fee, provided that the above copyright notice and this notice appears in all copies, and that the name of Hewlett-Packard Company not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Hewlett-Packard Company makes no representations about the suitability of this software for any purpose. (25) Henry Spencer (only *-linux targets) Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved. This software is not subject to any license of the American Telephone and Telegraph Company or of the Regents of the University of California. Permission is granted to anyone to use this software for any purpose on any computer system, and to alter it and redistribute it, subject to the following restrictions: 1. The author is not responsible for the consequences of use of this software, no matter how awful, even if they arise from flaws in it. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. Since few users ever read sources, credits must appear in the documentation. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. Since few users ever read sources, credits must appear in the documentation. 4. This notice may not be removed or altered. (26) Mike Barcroft Copyright (c) 2001 Mike Barcroft All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (27) Konstantin Chuguev (--enable-newlib-iconv) Copyright (c) 1999, 2000 Konstantin Chuguev. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. iconv (Charset Conversion Library) v2.0 (28) Artem Bityuckiy (--enable-newlib-iconv) Copyright (c) 2003, Artem B. Bityuckiy, SoftMine Corporation. Rights transferred to Franklin Electronic Publishers. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (29) IBM, Sony, Toshiba (only spu-* targets) (C) Copyright 2001,2006, International Business Machines Corporation, Sony Computer Entertainment, Incorporated, Toshiba Corporation, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the names of the copyright holders nor the names of their contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (30) - Alex Tatmanjants (targets using libc/posix) Copyright (c) 1995 Alex Tatmanjants at Electronni Visti IA, Kiev, Ukraine. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (31) - M. Warner Losh (targets using libc/posix) Copyright (c) 1998, M. Warner Losh All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (32) - Andrey A. Chernov (targets using libc/posix) Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (33) - Daniel Eischen (targets using libc/posix) Copyright (c) 2001 Daniel Eischen . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (34) - Jon Beniston (only lm32-* targets) Contributed by Jon Beniston Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (35) - ARM Ltd (arm and thumb variant targets only) Copyright (c) 2009 ARM Ltd All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the company may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (36) - Xilinx, Inc. (microblaze-* and powerpc-* targets) Copyright (c) 2004, 2009 Xilinx, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Xilinx nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (37) Texas Instruments Incorporated (tic6x-*, *-tirtos targets) Copyright (c) 1996-2010,2014 Texas Instruments Incorporated http://www.ti.com/ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of Texas Instruments Incorporated nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (38) National Semiconductor (cr16-* and crx-* targets) Copyright (c) 2004 National Semiconductor Corporation The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. (39) - Adapteva, Inc. (epiphany-* targets) Copyright (c) 2011, Adapteva, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Adapteva nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (40) - Altera Corportion (nios2-* targets) Copyright (c) 2003 Altera Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: o Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. o Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. o Neither the name of Altera Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY ALTERA CORPORATION, THE COPYRIGHT HOLDER, AND ITS CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (41) Ed Schouten - Free BSD Copyright (c) 2008 Ed Schouten All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: arch/README ================================================ MULTI-PLATFORM SUPPORT FOR MEGAZEUX The arch/ directory structure contains any code/machinery which is platform specific. Though is it dubiously named "arch" this refers to the platform "architecture" rather than the CPU architecture. For example, although GP2X and NDS both use ARM CPUs, they require different library and build system machinery to work correctly. DIRECTORY LAYOUT Most directories here contain at least a README file describing what toolchain and dependencies they require to work correctly. Some might also define additional targets, for post-processing binaries or installing them on the system. Additionally, all of these directories must have a Makefile.in which the build system will automatically include. This file should initialize any variables that can be tweaked, for example the location of libraries or compiler flags. The existing Makefile.in files should be a reasonable guide to this functionality. ADDING A PLATFORM TO MEGAZEUX Adding support for a new platform is trivial. Think of a short name for the platform (for example, Nintendo Dual-Screen is "nds") then create a directory in arch/ with that name. Create a Makefile.in for your platform. Initially, you may find configuring for "unix" and then manually altering the "platform.inc" in the top level is enough to get your build to succeed. Then, some changes must be made to config.sh to automatically generate both the src/config.h header (which is fully generic) and the platform.inc. This script is what users of your port will invoke to build the package. You may also want to make sure the "build" and "archive" targets do something for your platform. These targets make auto-builds and shipping binary packages much easier. LICENSES If your port requires reporting extra software licenses, you should put a notification in LICENSE.3rd. If the boilerplate isn't reasonably small, it should go in this folder named in the format "LICENSE.[license here]". In this situation, add the license filename to EXTRA_LICENSES so it will be shipped with relevant builds. ================================================ FILE: arch/amiga/CONFIG.AMIGA ================================================ #!/bin/sh ./config.sh --platform amiga --prefix /usr/local/amiga \ --disable-libpng --disable-utils --enable-release "$@" ================================================ FILE: arch/amiga/MZXRun ================================================ STACK 1000000 Assign >NIL: "USR:" EXISTS IF NOT WARN ELSE Assign USR: RAM: ENDIF Assign >NIL: "ETC:" EXISTS IF NOT WARN ELSE Assign ETC: RAM: ENDIF run >NIL: mzxrun.exe; ================================================ FILE: arch/amiga/Makefile.in ================================================ # # amiga makefile generics # CC = ppc-amigaos-gcc -mcrt=clib2 -I${PREFIX}/clib2/include CXX = ppc-amigaos-g++ -mcrt=clib2 -I${PREFIX}/clib2/include STRIP = ppc-amigaos-strip OBJCOPY = true CHMOD = true BINEXT = .exe DSOLDFLAGS = -shared DSOPRE = lib DSOPOST = .so DSORPATH = -Wl,-rpath,${LIBDIR} DSOSONAME = -Wl,-soname, # Block --host, which will break things. CROSS_COMPILE = ifeq (${BUILD_MODULAR},1) ARCH_CFLAGS += -fPIC ARCH_CXXFLAGS += -fPIC ARCH_LDFLAGS += -use-dynld -lunix endif # MZX breaks this optimisation on Amiga ARCH_CFLAGS += -fno-strict-aliasing ARCH_CXXFLAGS += -fno-strict-aliasing # Amiga needs PNG to be statically linked (inc. zlib) LIBPNG_LDFLAGS = $(shell libpng12-config --static --ldflags) # # Need to nest Amiga binaries in a subdir # build := ${build_root}/MegaZeux build: ${build} ${CP} arch/amiga/MegaZeux.info ${build} ${CP} arch/amiga/MegaZeux.info ${build}/MZXRun.info ${CP} arch/amiga/MegaZeux.info ${build_root} ${CP} arch/amiga/MegaZeux arch/amiga/MZXRun ${build} ${RM} ${build}/*.debug include arch/lha.inc ================================================ FILE: arch/amiga/MegaZeux ================================================ STACK 1000000 Assign >NIL: "USR:" EXISTS IF NOT WARN ELSE Assign USR: RAM: ENDIF Assign >NIL: "ETC:" EXISTS IF NOT WARN ELSE Assign ETC: RAM: ENDIF run >NIL: megazeux.exe; ================================================ FILE: arch/amiga/README ================================================ MEGAZEUX ON AMIGA OS 4 Since 2.82b, MegaZeux supports cross compilation to Amiga OS 4. You will require a valid copy of the operating system software in order to run the final result; this is not a bare-metal Amiga binary. The only supported toolchain is for OS 4 and PPC Amigas. m68k Amigas are not supported. PREPARATION The port requires that the Amiga OS 4 SDK and toolchain is installed. There are several pre-built toolchains available from: http://cross.zerohero.se/os4.html There is an excellent guide for linking your toolchain and the platform SDK together here: http://utilitybase.com/article/show/2007/06/23/231/Installing+an+AmigaOS+4+cross+compiler The SDL library for AmigaOS 4 (clib2) must be installed. I got my copy from: http://www.rcdrummond.net/sdl/index.html BUILDING MEGAZEUX First, configure MZX. A suitable config.sh command line is provided in CONFIG.AMIGA present in this subdirectory. Please note that --prefix MUST correctly point to the AmigaOS 4 SDK (otherwise it tries to use /usr's stub headers and fails). Then start the build with "make". INSTALLING MEGAZEUX The usual "make archive" works to generate an LHA compilation of MegaZeux binaries and Amiga specific scripts. Icons are provided where appropriate. --ajs ================================================ FILE: arch/android/CONFIG.ANDROID ================================================ #!/bin/sh # TODO: GL fixed renderers don't work. Probably not worth fixing. [ -z "$NDK_PATH" ] && { echo "Must define NDK_PATH!"; exit 1; } ./config.sh --platform android --enable-release --enable-lto \ --disable-utils --disable-libpng --disable-gl-fixed "$@" ================================================ FILE: arch/android/Makefile.deps ================================================ # # Makefile fragment for building, installing, or uninstalling Android dependencies. # Dependencies are installed into the project JNI libs dir and arch/android/includes. # # This should not be used directly, but should be used from Makefile.in. # This file relies on several variables defined by Makefile.in. # .PHONY: deps-build deps-install deps-uninstall ifeq (${NDK_PATH},) $(error "Must define $$NDK_PATH!") endif # # NOTE: when updating the SDL_VERSION field here, the SDL android project code # in arch/android/project/app/src/main/org/libsdl/app/ needs to be updated with # the android project from the new SDL release (SDL/android-project/app/src/...). # SDL_VERSION ?= 2.30.9 LIBOGG_VERSION ?= 1.3.5 LIBVORBIS_VERSION ?= 1.3.7 WGET ?= wget TAR ?= tar PATCH ?= patch DEPS := arch/android/deps DEPS_BUILD := arch/android/deps/.build NDK_BUILD := ${NDK_PATH}/ndk-build ifeq (${HOST},${HOST_WIN32}) NDK_BUILD := ${NDK_PATH}/ndk-build.cmd endif ifeq (${HOST},${HOST_WIN64}) NDK_BUILD := ${NDK_PATH}/ndk-build.cmd endif ifneq (${V},1) WGET := @${WGET} TAR := @${TAR} NDK_BUILD := @${NDK_BUILD} endif ${DEPS} ${JNI_INCLUDES}: $(if @{V},,@echo " MKDIR " $@) ${MKDIR} -p $@ ifeq (${ANDROID_TARGET},) ${DEPS}/SDL2-${SDL_VERSION}: | ${DEPS} $(if ${V},,@echo " WGET " $@) ${RM} -f $@.tar.gz ${WGET} https://www.libsdl.org/release/SDL2-${SDL_VERSION}.tar.gz -O$@.tar.gz ${TAR} -xzf $@.tar.gz -C ${DEPS}/ ${PATCH} -i ../../SDL2-page-sizes.patch -p1 -d ${DEPS}/SDL2-${SDL_VERSION} ${DEPS}/libogg-${LIBOGG_VERSION}: | ${DEPS} $(if ${V},,@echo " WGET " $@) ${RM} -f $@.tar.gz ${WGET} http://downloads.xiph.org/releases/ogg/libogg-${LIBOGG_VERSION}.tar.gz -O$@.tar.gz ${TAR} -xzf $@.tar.gz -C ${DEPS}/ ${DEPS}/libvorbis-${LIBVORBIS_VERSION}: | ${DEPS} $(if ${V},,@echo " WGET " $@) ${RM} -f $@.tar.gz ${WGET} http://downloads.xiph.org/releases/vorbis/libvorbis-${LIBVORBIS_VERSION}.tar.gz -O$@.tar.gz ${TAR} -xzf $@.tar.gz -C ${DEPS}/ ${DEPS_BUILD}: $(if ${V},,@echo " MKDIR " $@) ${MKDIR} -p ${DEPS_BUILD} ${DEPS_BUILD}/libogg: ${DEPS}/libogg-${LIBOGG_VERSION} | ${DEPS_BUILD} ${RM} -rf $@ ${CP} -r $< $@ ${CP} arch/android/libogg-Android.mk "$@/Android.mk" ${CP} arch/android/config_types.h "$@/include/ogg/" ${DEPS_BUILD}/libvorbis: ${DEPS}/libvorbis-${LIBVORBIS_VERSION} | ${DEPS_BUILD} ${RM} -rf $@ ${CP} -r $< $@ ${CP} arch/android/libvorbis-Android.mk "$@/Android.mk" ${DEPS_BUILD}/SDL2: ${DEPS}/SDL2-${SDL_VERSION} | ${DEPS_BUILD} ${RM} -rf $@ ${CP} -r $< $@ ${DEPS_BUILD}/out: ${DEPS_BUILD}/libogg ${DEPS_BUILD}/libvorbis ${DEPS_BUILD}/SDL2 ${CP} ${JNI_DIR}/Android.mk ${DEPS_BUILD} $(if ${V},,@echo " NDKBUILD") ${NDK_BUILD} \ NDK_PROJECT_PATH="${DEPS_BUILD}" \ NDK_LIBS_OUT="${DEPS_BUILD}/out" \ APP_BUILD_SCRIPT="${DEPS_BUILD}/Android.mk" \ APP_ABI="armeabi-v7a arm64-v8a x86 x86_64" \ APP_PLATFORM="android-16" deps-build: ${DEPS_BUILD}/out else dep_targets := \ ${JNI_INCLUDES}/SDL2 \ ${JNI_INCLUDES}/ogg \ ${JNI_INCLUDES}/vorbis \ ${JNI_LIBS}/libSDL2.so \ ${JNI_LIBS}/libogg.so \ ${JNI_LIBS}/libvorbis.so \ ${JNI_LIBS}/libvorbisfile.so ${DEPS_BUILD}/out/${ABI}/%.so: @test -f $@ || { echo "Missing $@! Aborting..."; exit 1; } ${JNI_LIBS}/%.so: ${DEPS_BUILD}/out/${ABI}/%.so | ${JNI_LIBS} $(if ${V},,@echo " CP " $< " " $@) ${CP} $< $@ ${JNI_INCLUDES}/SDL2: ${DEPS_BUILD}/SDL2 | ${JNI_INCLUDES} $(if ${V},,@echo " CP " "$ typedef int16_t ogg_int16_t; typedef uint16_t ogg_uint16_t; typedef int32_t ogg_int32_t; typedef uint32_t ogg_uint32_t; typedef int64_t ogg_int64_t; typedef uint64_t ogg_uint64_t; #endif ================================================ FILE: arch/android/libogg-Android.mk ================================================ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libogg LOCAL_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) # https://developer.android.com/guide/practices/page-sizes LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384" LOCAL_SRC_FILES := src/bitwise.c src/framing.c include $(BUILD_SHARED_LIBRARY) ================================================ FILE: arch/android/libvorbis-Android.mk ================================================ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libvorbis LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/lib LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_SHARED_LIBRARIES := libogg # https://developer.android.com/guide/practices/page-sizes LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384" LOCAL_SRC_FILES := lib/mdct.c lib/smallft.c lib/block.c lib/envelope.c lib/window.c lib/lsp.c \ lib/lpc.c lib/analysis.c lib/synthesis.c lib/psy.c lib/info.c \ lib/floor1.c lib/floor0.c \ lib/res0.c lib/mapping0.c lib/registry.c lib/codebook.c lib/sharedbook.c \ lib/lookup.c lib/bitrate.c include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := libvorbisfile LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/lib LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_SHARED_LIBRARIES := libogg libvorbis # https://developer.android.com/guide/practices/page-sizes LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384" LOCAL_SRC_FILES := lib/vorbisfile.c include $(BUILD_SHARED_LIBRARY) ================================================ FILE: arch/android/project/app/build.gradle ================================================ def buildAsLibrary = project.hasProperty('BUILD_AS_LIBRARY'); def buildAsApplication = !buildAsLibrary if (buildAsApplication) { apply plugin: 'com.android.application' } else { apply plugin: 'com.android.library' } // Create a variable called keystorePropertiesFile, and initialize it to your // keystore.properties file, in the rootProject folder. def keystorePropertiesFile = rootProject.file("keystore.properties") // Initialize a new Properties() object called keystoreProperties. def keystoreProperties = new Properties() // Load your keystore.properties file into the keystoreProperties object. keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) android { signingConfigs { release { storeFile file(keystoreProperties['storeFile']) storePassword keystoreProperties['storePassword'] keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] } } namespace "net.digitalmzx.megazeux" ndkVersion "23.2.8568313" compileSdkVersion 34 buildToolsVersion "34.0.0" defaultConfig { if (buildAsApplication) { applicationId "net.digitalmzx.megazeux" } minSdkVersion 16 targetSdkVersion 34 versionCode 1 versionName "1.0" externalNativeBuild { ndkBuild { arguments "APP_PLATFORM=android-16" abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release } } if (!project.hasProperty('EXCLUDE_NATIVE_LIBS')) { sourceSets.main { jniLibs.srcDir 'jni/lib' } externalNativeBuild { ndkBuild { path 'jni/Android.mk' } } } lint { abortOnError false } compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } if (buildAsLibrary) { libraryVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile if (outputFile != null && outputFile.name.endsWith(".aar")) { def fileName = "org.libsdl.app.aar"; output.outputFile = new File(outputFile.parent, fileName); } } } } } dependencies { } ================================================ FILE: arch/android/project/app/jni/Android.mk ================================================ include $(call all-subdir-makefiles) ================================================ FILE: arch/android/project/app/jni/Application.mk ================================================ # Uncomment this if you're using STL in your project # See CPLUSPLUS-SUPPORT.html in the NDK documentation for more information # APP_STL := stlport_static # Min runtime API level APP_PLATFORM=android-16 ================================================ FILE: arch/android/project/app/jni/main/Android.mk ================================================ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := main LOCAL_SRC_FILES := ../lib/$(TARGET_ARCH_ABI)/libmain.so LOCAL_SHARED_LIBRARIES := SDL2 ogg vorbis include $(PREBUILT_SHARED_LIBRARY) ================================================ FILE: arch/android/project/app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in [sdk]/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: arch/android/project/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: arch/android/project/app/src/main/java/net/digitalmzx/megazeux/GameActivity.java ================================================ /* MegaZeux * * Copyright (C) 2019 Adrian Siekierka * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package net.digitalmzx.megazeux; import android.app.Activity; import android.os.Build; import android.os.Environment; import android.view.View; import org.libsdl.app.SDLActivity; import java.io.File; public class GameActivity extends SDLActivity { static File getAssetPath(Activity activity) { File extDir = activity.getExternalFilesDir(null); if(extDir == null) { extDir = new File(Environment.getExternalStorageDirectory(), "data/megazeux"); if(!extDir.exists()) { //noinspection StatementWithEmptyBody if(!extDir.mkdirs()) { // pass } } } return extDir; } @Override protected String[] getArguments() { return new String[] { new File(getAssetPath(this), "megazeux").getAbsolutePath() }; } } ================================================ FILE: arch/android/project/app/src/main/java/net/digitalmzx/megazeux/MainActivity.java ================================================ /* MegaZeux * * Copyright (C) 2019 Adrian Siekierka * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package net.digitalmzx.megazeux; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.app.Activity; import android.os.Environment; import android.provider.Settings; import android.view.View; import java.io.File; import java.io.FileOutputStream; import java.io.IOError; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; public class MainActivity extends Activity { private static final int MANAGE_EXTERNAL_STORAGE_INTENT_CODE = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Ensure all necessary permissions are present if(Build.VERSION.SDK_INT >= 30 /* Android 11.0 */) { if(!Environment.isExternalStorageManager()) { try { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, MANAGE_EXTERNAL_STORAGE_INTENT_CODE); } catch (Exception e) { Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); startActivityForResult(intent, MANAGE_EXTERNAL_STORAGE_INTENT_CODE); } return; } } else if(Build.VERSION.SDK_INT >= 23 /* Android 6.0 */) { if(checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1000); return; } } launchGame(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(Build.VERSION.SDK_INT >= 30 /* Android 11.0 */) { if(requestCode == MANAGE_EXTERNAL_STORAGE_INTENT_CODE) { if(Environment.isExternalStorageManager()) launchGame(); } } } private void launchGame() { // unzip assets File targetPath = GameActivity.getAssetPath(this); InputStream assetStream = getResources().openRawResource(R.raw.assets); ZipInputStream assetZip = new ZipInputStream(assetStream); byte[] buffer = new byte[8192]; FileOutputStream output = null; try { ZipEntry entry; while((entry = assetZip.getNextEntry()) != null) { File target = new File(targetPath, entry.getName()); if(entry.isDirectory()) { if(target.exists()) continue; target.mkdirs(); } else { if(target.exists()) { if(target.lastModified() >= entry.getTime()) continue; } int read; output = new FileOutputStream(target); while((read = assetZip.read(buffer, 0, buffer.length)) >= 0) { output.write(buffer, 0, read); } output.close(); output = null; target.setLastModified(entry.getTime()); } assetZip.closeEntry(); } } catch(IOException e) { throw new RuntimeException(e); } finally { if(output != null) { try { output.close(); } catch(IOException e) { // pass } } try { assetZip.close(); } catch(IOException e) { // pass } try { assetStream.close(); } catch(IOException e) { // pass } } // launch game startActivity(new Intent(getApplicationContext(), GameActivity.class)); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { launchGame(); } } } ================================================ FILE: arch/android/project/app/src/main/java/org/libsdl/app/HIDDevice.java ================================================ package org.libsdl.app; import android.hardware.usb.UsbDevice; interface HIDDevice { public int getId(); public int getVendorId(); public int getProductId(); public String getSerialNumber(); public int getVersion(); public String getManufacturerName(); public String getProductName(); public UsbDevice getDevice(); public boolean open(); public int sendFeatureReport(byte[] report); public int sendOutputReport(byte[] report); public boolean getFeatureReport(byte[] report); public void setFrozen(boolean frozen); public void close(); public void shutdown(); } ================================================ FILE: arch/android/project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java ================================================ package org.libsdl.app; import android.content.Context; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothGattService; import android.hardware.usb.UsbDevice; import android.os.Handler; import android.os.Looper; import android.util.Log; import android.os.*; //import com.android.internal.util.HexDump; import java.lang.Runnable; import java.util.Arrays; import java.util.LinkedList; import java.util.UUID; class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDevice { private static final String TAG = "hidapi"; private HIDDeviceManager mManager; private BluetoothDevice mDevice; private int mDeviceId; private BluetoothGatt mGatt; private boolean mIsRegistered = false; private boolean mIsConnected = false; private boolean mIsChromebook = false; private boolean mIsReconnecting = false; private boolean mFrozen = false; private LinkedList mOperations; GattOperation mCurrentOperation = null; private Handler mHandler; private static final int TRANSPORT_AUTO = 0; private static final int TRANSPORT_BREDR = 1; private static final int TRANSPORT_LE = 2; private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000; static public final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3"); static public final UUID inputCharacteristic = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3"); static public final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3"); static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 }; static class GattOperation { private enum Operation { CHR_READ, CHR_WRITE, ENABLE_NOTIFICATION } Operation mOp; UUID mUuid; byte[] mValue; BluetoothGatt mGatt; boolean mResult = true; private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid) { mGatt = gatt; mOp = operation; mUuid = uuid; } private GattOperation(BluetoothGatt gatt, GattOperation.Operation operation, UUID uuid, byte[] value) { mGatt = gatt; mOp = operation; mUuid = uuid; mValue = value; } public void run() { // This is executed in main thread BluetoothGattCharacteristic chr; switch (mOp) { case CHR_READ: chr = getCharacteristic(mUuid); //Log.v(TAG, "Reading characteristic " + chr.getUuid()); if (!mGatt.readCharacteristic(chr)) { Log.e(TAG, "Unable to read characteristic " + mUuid.toString()); mResult = false; break; } mResult = true; break; case CHR_WRITE: chr = getCharacteristic(mUuid); //Log.v(TAG, "Writing characteristic " + chr.getUuid() + " value=" + HexDump.toHexString(value)); chr.setValue(mValue); if (!mGatt.writeCharacteristic(chr)) { Log.e(TAG, "Unable to write characteristic " + mUuid.toString()); mResult = false; break; } mResult = true; break; case ENABLE_NOTIFICATION: chr = getCharacteristic(mUuid); //Log.v(TAG, "Writing descriptor of " + chr.getUuid()); if (chr != null) { BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")); if (cccd != null) { int properties = chr.getProperties(); byte[] value; if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) == BluetoothGattCharacteristic.PROPERTY_NOTIFY) { value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE; } else if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) == BluetoothGattCharacteristic.PROPERTY_INDICATE) { value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE; } else { Log.e(TAG, "Unable to start notifications on input characteristic"); mResult = false; return; } mGatt.setCharacteristicNotification(chr, true); cccd.setValue(value); if (!mGatt.writeDescriptor(cccd)) { Log.e(TAG, "Unable to write descriptor " + mUuid.toString()); mResult = false; return; } mResult = true; } } } } public boolean finish() { return mResult; } private BluetoothGattCharacteristic getCharacteristic(UUID uuid) { BluetoothGattService valveService = mGatt.getService(steamControllerService); if (valveService == null) return null; return valveService.getCharacteristic(uuid); } static public GattOperation readCharacteristic(BluetoothGatt gatt, UUID uuid) { return new GattOperation(gatt, Operation.CHR_READ, uuid); } static public GattOperation writeCharacteristic(BluetoothGatt gatt, UUID uuid, byte[] value) { return new GattOperation(gatt, Operation.CHR_WRITE, uuid, value); } static public GattOperation enableNotification(BluetoothGatt gatt, UUID uuid) { return new GattOperation(gatt, Operation.ENABLE_NOTIFICATION, uuid); } } public HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) { mManager = manager; mDevice = device; mDeviceId = mManager.getDeviceIDForIdentifier(getIdentifier()); mIsRegistered = false; mIsChromebook = mManager.getContext().getPackageManager().hasSystemFeature("org.chromium.arc.device_management"); mOperations = new LinkedList(); mHandler = new Handler(Looper.getMainLooper()); mGatt = connectGatt(); // final HIDDeviceBLESteamController finalThis = this; // mHandler.postDelayed(new Runnable() { // @Override // public void run() { // finalThis.checkConnectionForChromebookIssue(); // } // }, CHROMEBOOK_CONNECTION_CHECK_INTERVAL); } public String getIdentifier() { return String.format("SteamController.%s", mDevice.getAddress()); } public BluetoothGatt getGatt() { return mGatt; } // Because on Chromebooks we show up as a dual-mode device, it will attempt to connect TRANSPORT_AUTO, which will use TRANSPORT_BREDR instead // of TRANSPORT_LE. Let's force ourselves to connect low energy. private BluetoothGatt connectGatt(boolean managed) { if (Build.VERSION.SDK_INT >= 23 /* Android 6.0 (M) */) { try { return mDevice.connectGatt(mManager.getContext(), managed, this, TRANSPORT_LE); } catch (Exception e) { return mDevice.connectGatt(mManager.getContext(), managed, this); } } else { return mDevice.connectGatt(mManager.getContext(), managed, this); } } private BluetoothGatt connectGatt() { return connectGatt(false); } protected int getConnectionState() { Context context = mManager.getContext(); if (context == null) { // We are lacking any context to get our Bluetooth information. We'll just assume disconnected. return BluetoothProfile.STATE_DISCONNECTED; } BluetoothManager btManager = (BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE); if (btManager == null) { // This device doesn't support Bluetooth. We should never be here, because how did // we instantiate a device to start with? return BluetoothProfile.STATE_DISCONNECTED; } return btManager.getConnectionState(mDevice, BluetoothProfile.GATT); } public void reconnect() { if (getConnectionState() != BluetoothProfile.STATE_CONNECTED) { mGatt.disconnect(); mGatt = connectGatt(); } } protected void checkConnectionForChromebookIssue() { if (!mIsChromebook) { // We only do this on Chromebooks, because otherwise it's really annoying to just attempt // over and over. return; } int connectionState = getConnectionState(); switch (connectionState) { case BluetoothProfile.STATE_CONNECTED: if (!mIsConnected) { // We are in the Bad Chromebook Place. We can force a disconnect // to try to recover. Log.v(TAG, "Chromebook: We are in a very bad state; the controller shows as connected in the underlying Bluetooth layer, but we never received a callback. Forcing a reconnect."); mIsReconnecting = true; mGatt.disconnect(); mGatt = connectGatt(false); break; } else if (!isRegistered()) { if (mGatt.getServices().size() > 0) { Log.v(TAG, "Chromebook: We are connected to a controller, but never got our registration. Trying to recover."); probeService(this); } else { Log.v(TAG, "Chromebook: We are connected to a controller, but never discovered services. Trying to recover."); mIsReconnecting = true; mGatt.disconnect(); mGatt = connectGatt(false); break; } } else { Log.v(TAG, "Chromebook: We are connected, and registered. Everything's good!"); return; } break; case BluetoothProfile.STATE_DISCONNECTED: Log.v(TAG, "Chromebook: We have either been disconnected, or the Chromebook BtGatt.ContextMap bug has bitten us. Attempting a disconnect/reconnect, but we may not be able to recover."); mIsReconnecting = true; mGatt.disconnect(); mGatt = connectGatt(false); break; case BluetoothProfile.STATE_CONNECTING: Log.v(TAG, "Chromebook: We're still trying to connect. Waiting a bit longer."); break; } final HIDDeviceBLESteamController finalThis = this; mHandler.postDelayed(new Runnable() { @Override public void run() { finalThis.checkConnectionForChromebookIssue(); } }, CHROMEBOOK_CONNECTION_CHECK_INTERVAL); } private boolean isRegistered() { return mIsRegistered; } private void setRegistered() { mIsRegistered = true; } private boolean probeService(HIDDeviceBLESteamController controller) { if (isRegistered()) { return true; } if (!mIsConnected) { return false; } Log.v(TAG, "probeService controller=" + controller); for (BluetoothGattService service : mGatt.getServices()) { if (service.getUuid().equals(steamControllerService)) { Log.v(TAG, "Found Valve steam controller service " + service.getUuid()); for (BluetoothGattCharacteristic chr : service.getCharacteristics()) { if (chr.getUuid().equals(inputCharacteristic)) { Log.v(TAG, "Found input characteristic"); // Start notifications BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")); if (cccd != null) { enableNotification(chr.getUuid()); } } } return true; } } if ((mGatt.getServices().size() == 0) && mIsChromebook && !mIsReconnecting) { Log.e(TAG, "Chromebook: Discovered services were empty; this almost certainly means the BtGatt.ContextMap bug has bitten us."); mIsConnected = false; mIsReconnecting = true; mGatt.disconnect(); mGatt = connectGatt(false); } return false; } ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// private void finishCurrentGattOperation() { GattOperation op = null; synchronized (mOperations) { if (mCurrentOperation != null) { op = mCurrentOperation; mCurrentOperation = null; } } if (op != null) { boolean result = op.finish(); // TODO: Maybe in main thread as well? // Our operation failed, let's add it back to the beginning of our queue. if (!result) { mOperations.addFirst(op); } } executeNextGattOperation(); } private void executeNextGattOperation() { synchronized (mOperations) { if (mCurrentOperation != null) return; if (mOperations.isEmpty()) return; mCurrentOperation = mOperations.removeFirst(); } // Run in main thread mHandler.post(new Runnable() { @Override public void run() { synchronized (mOperations) { if (mCurrentOperation == null) { Log.e(TAG, "Current operation null in executor?"); return; } mCurrentOperation.run(); // now wait for the GATT callback and when it comes, finish this operation } } }); } private void queueGattOperation(GattOperation op) { synchronized (mOperations) { mOperations.add(op); } executeNextGattOperation(); } private void enableNotification(UUID chrUuid) { GattOperation op = HIDDeviceBLESteamController.GattOperation.enableNotification(mGatt, chrUuid); queueGattOperation(op); } public void writeCharacteristic(UUID uuid, byte[] value) { GattOperation op = HIDDeviceBLESteamController.GattOperation.writeCharacteristic(mGatt, uuid, value); queueGattOperation(op); } public void readCharacteristic(UUID uuid) { GattOperation op = HIDDeviceBLESteamController.GattOperation.readCharacteristic(mGatt, uuid); queueGattOperation(op); } ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////// BluetoothGattCallback overridden methods ////////////////////////////////////////////////////////////////////////////////////////////////////// public void onConnectionStateChange(BluetoothGatt g, int status, int newState) { //Log.v(TAG, "onConnectionStateChange status=" + status + " newState=" + newState); mIsReconnecting = false; if (newState == 2) { mIsConnected = true; // Run directly, without GattOperation if (!isRegistered()) { mHandler.post(new Runnable() { @Override public void run() { mGatt.discoverServices(); } }); } } else if (newState == 0) { mIsConnected = false; } // Disconnection is handled in SteamLink using the ACTION_ACL_DISCONNECTED Intent. } public void onServicesDiscovered(BluetoothGatt gatt, int status) { //Log.v(TAG, "onServicesDiscovered status=" + status); if (status == 0) { if (gatt.getServices().size() == 0) { Log.v(TAG, "onServicesDiscovered returned zero services; something has gone horribly wrong down in Android's Bluetooth stack."); mIsReconnecting = true; mIsConnected = false; gatt.disconnect(); mGatt = connectGatt(false); } else { probeService(this); } } } public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { //Log.v(TAG, "onCharacteristicRead status=" + status + " uuid=" + characteristic.getUuid()); if (characteristic.getUuid().equals(reportCharacteristic) && !mFrozen) { mManager.HIDDeviceFeatureReport(getId(), characteristic.getValue()); } finishCurrentGattOperation(); } public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { //Log.v(TAG, "onCharacteristicWrite status=" + status + " uuid=" + characteristic.getUuid()); if (characteristic.getUuid().equals(reportCharacteristic)) { // Only register controller with the native side once it has been fully configured if (!isRegistered()) { Log.v(TAG, "Registering Steam Controller with ID: " + getId()); mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0); setRegistered(); } } finishCurrentGattOperation(); } public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { // Enable this for verbose logging of controller input reports //Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue())); if (characteristic.getUuid().equals(inputCharacteristic) && !mFrozen) { mManager.HIDDeviceInputReport(getId(), characteristic.getValue()); } } public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { //Log.v(TAG, "onDescriptorRead status=" + status); } public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { BluetoothGattCharacteristic chr = descriptor.getCharacteristic(); //Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid()); if (chr.getUuid().equals(inputCharacteristic)) { boolean hasWrittenInputDescriptor = true; BluetoothGattCharacteristic reportChr = chr.getService().getCharacteristic(reportCharacteristic); if (reportChr != null) { Log.v(TAG, "Writing report characteristic to enter valve mode"); reportChr.setValue(enterValveMode); gatt.writeCharacteristic(reportChr); } } finishCurrentGattOperation(); } public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { //Log.v(TAG, "onReliableWriteCompleted status=" + status); } public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { //Log.v(TAG, "onReadRemoteRssi status=" + status); } public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { //Log.v(TAG, "onMtuChanged status=" + status); } ////////////////////////////////////////////////////////////////////////////////////////////////////// //////// Public API ////////////////////////////////////////////////////////////////////////////////////////////////////// @Override public int getId() { return mDeviceId; } @Override public int getVendorId() { // Valve Corporation final int VALVE_USB_VID = 0x28DE; return VALVE_USB_VID; } @Override public int getProductId() { // We don't have an easy way to query from the Bluetooth device, but we know what it is final int D0G_BLE2_PID = 0x1106; return D0G_BLE2_PID; } @Override public String getSerialNumber() { // This will be read later via feature report by Steam return "12345"; } @Override public int getVersion() { return 0; } @Override public String getManufacturerName() { return "Valve Corporation"; } @Override public String getProductName() { return "Steam Controller"; } @Override public UsbDevice getDevice() { return null; } @Override public boolean open() { return true; } @Override public int sendFeatureReport(byte[] report) { if (!isRegistered()) { Log.e(TAG, "Attempted sendFeatureReport before Steam Controller is registered!"); if (mIsConnected) { probeService(this); } return -1; } // We need to skip the first byte, as that doesn't go over the air byte[] actual_report = Arrays.copyOfRange(report, 1, report.length - 1); //Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(actual_report)); writeCharacteristic(reportCharacteristic, actual_report); return report.length; } @Override public int sendOutputReport(byte[] report) { if (!isRegistered()) { Log.e(TAG, "Attempted sendOutputReport before Steam Controller is registered!"); if (mIsConnected) { probeService(this); } return -1; } //Log.v(TAG, "sendFeatureReport " + HexDump.dumpHexString(report)); writeCharacteristic(reportCharacteristic, report); return report.length; } @Override public boolean getFeatureReport(byte[] report) { if (!isRegistered()) { Log.e(TAG, "Attempted getFeatureReport before Steam Controller is registered!"); if (mIsConnected) { probeService(this); } return false; } //Log.v(TAG, "getFeatureReport"); readCharacteristic(reportCharacteristic); return true; } @Override public void close() { } @Override public void setFrozen(boolean frozen) { mFrozen = frozen; } @Override public void shutdown() { close(); BluetoothGatt g = mGatt; if (g != null) { g.disconnect(); g.close(); mGatt = null; } mManager = null; mIsRegistered = false; mIsConnected = false; mOperations.clear(); } } ================================================ FILE: arch/android/project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java ================================================ package org.libsdl.app; import android.app.Activity; import android.app.AlertDialog; import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.os.Build; import android.util.Log; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.hardware.usb.*; import android.os.Handler; import android.os.Looper; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; public class HIDDeviceManager { private static final String TAG = "hidapi"; private static final String ACTION_USB_PERMISSION = "org.libsdl.app.USB_PERMISSION"; private static HIDDeviceManager sManager; private static int sManagerRefCount = 0; public static HIDDeviceManager acquire(Context context) { if (sManagerRefCount == 0) { sManager = new HIDDeviceManager(context); } ++sManagerRefCount; return sManager; } public static void release(HIDDeviceManager manager) { if (manager == sManager) { --sManagerRefCount; if (sManagerRefCount == 0) { sManager.close(); sManager = null; } } } private Context mContext; private HashMap mDevicesById = new HashMap(); private HashMap mBluetoothDevices = new HashMap(); private int mNextDeviceId = 0; private SharedPreferences mSharedPreferences = null; private boolean mIsChromebook = false; private UsbManager mUsbManager; private Handler mHandler; private BluetoothManager mBluetoothManager; private List mLastBluetoothDevices; private final BroadcastReceiver mUsbBroadcast = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) { UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); handleUsbDeviceAttached(usbDevice); } else if (action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) { UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); handleUsbDeviceDetached(usbDevice); } else if (action.equals(HIDDeviceManager.ACTION_USB_PERMISSION)) { UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); handleUsbDevicePermission(usbDevice, intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)); } } }; private final BroadcastReceiver mBluetoothBroadcast = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // Bluetooth device was connected. If it was a Steam Controller, handle it if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.d(TAG, "Bluetooth device connected: " + device); if (isSteamController(device)) { connectBluetoothDevice(device); } } // Bluetooth device was disconnected, remove from controller manager (if any) if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.d(TAG, "Bluetooth device disconnected: " + device); disconnectBluetoothDevice(device); } } }; private HIDDeviceManager(final Context context) { mContext = context; HIDDeviceRegisterCallback(); mSharedPreferences = mContext.getSharedPreferences("hidapi", Context.MODE_PRIVATE); mIsChromebook = mContext.getPackageManager().hasSystemFeature("org.chromium.arc.device_management"); // if (shouldClear) { // SharedPreferences.Editor spedit = mSharedPreferences.edit(); // spedit.clear(); // spedit.commit(); // } // else { mNextDeviceId = mSharedPreferences.getInt("next_device_id", 0); } } public Context getContext() { return mContext; } public int getDeviceIDForIdentifier(String identifier) { SharedPreferences.Editor spedit = mSharedPreferences.edit(); int result = mSharedPreferences.getInt(identifier, 0); if (result == 0) { result = mNextDeviceId++; spedit.putInt("next_device_id", mNextDeviceId); } spedit.putInt(identifier, result); spedit.commit(); return result; } private void initializeUSB() { mUsbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE); if (mUsbManager == null) { return; } /* // Logging for (UsbDevice device : mUsbManager.getDeviceList().values()) { Log.i(TAG,"Path: " + device.getDeviceName()); Log.i(TAG,"Manufacturer: " + device.getManufacturerName()); Log.i(TAG,"Product: " + device.getProductName()); Log.i(TAG,"ID: " + device.getDeviceId()); Log.i(TAG,"Class: " + device.getDeviceClass()); Log.i(TAG,"Protocol: " + device.getDeviceProtocol()); Log.i(TAG,"Vendor ID " + device.getVendorId()); Log.i(TAG,"Product ID: " + device.getProductId()); Log.i(TAG,"Interface count: " + device.getInterfaceCount()); Log.i(TAG,"---------------------------------------"); // Get interface details for (int index = 0; index < device.getInterfaceCount(); index++) { UsbInterface mUsbInterface = device.getInterface(index); Log.i(TAG," ***** *****"); Log.i(TAG," Interface index: " + index); Log.i(TAG," Interface ID: " + mUsbInterface.getId()); Log.i(TAG," Interface class: " + mUsbInterface.getInterfaceClass()); Log.i(TAG," Interface subclass: " + mUsbInterface.getInterfaceSubclass()); Log.i(TAG," Interface protocol: " + mUsbInterface.getInterfaceProtocol()); Log.i(TAG," Endpoint count: " + mUsbInterface.getEndpointCount()); // Get endpoint details for (int epi = 0; epi < mUsbInterface.getEndpointCount(); epi++) { UsbEndpoint mEndpoint = mUsbInterface.getEndpoint(epi); Log.i(TAG," ++++ ++++ ++++"); Log.i(TAG," Endpoint index: " + epi); Log.i(TAG," Attributes: " + mEndpoint.getAttributes()); Log.i(TAG," Direction: " + mEndpoint.getDirection()); Log.i(TAG," Number: " + mEndpoint.getEndpointNumber()); Log.i(TAG," Interval: " + mEndpoint.getInterval()); Log.i(TAG," Packet size: " + mEndpoint.getMaxPacketSize()); Log.i(TAG," Type: " + mEndpoint.getType()); } } } Log.i(TAG," No more devices connected."); */ // Register for USB broadcasts and permission completions IntentFilter filter = new IntentFilter(); filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); filter.addAction(HIDDeviceManager.ACTION_USB_PERMISSION); mContext.registerReceiver(mUsbBroadcast, filter); for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) { handleUsbDeviceAttached(usbDevice); } } UsbManager getUSBManager() { return mUsbManager; } private void shutdownUSB() { try { mContext.unregisterReceiver(mUsbBroadcast); } catch (Exception e) { // We may not have registered, that's okay } } private boolean isHIDDeviceInterface(UsbDevice usbDevice, UsbInterface usbInterface) { if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) { return true; } if (isXbox360Controller(usbDevice, usbInterface) || isXboxOneController(usbDevice, usbInterface)) { return true; } return false; } private boolean isXbox360Controller(UsbDevice usbDevice, UsbInterface usbInterface) { final int XB360_IFACE_SUBCLASS = 93; final int XB360_IFACE_PROTOCOL = 1; // Wired final int XB360W_IFACE_PROTOCOL = 129; // Wireless final int[] SUPPORTED_VENDORS = { 0x0079, // GPD Win 2 0x044f, // Thrustmaster 0x045e, // Microsoft 0x046d, // Logitech 0x056e, // Elecom 0x06a3, // Saitek 0x0738, // Mad Catz 0x07ff, // Mad Catz 0x0e6f, // PDP 0x0f0d, // Hori 0x1038, // SteelSeries 0x11c9, // Nacon 0x12ab, // Unknown 0x1430, // RedOctane 0x146b, // BigBen 0x1532, // Razer Sabertooth 0x15e4, // Numark 0x162e, // Joytech 0x1689, // Razer Onza 0x1949, // Lab126, Inc. 0x1bad, // Harmonix 0x20d6, // PowerA 0x24c6, // PowerA 0x2c22, // Qanba 0x2dc8, // 8BitDo 0x9886, // ASTRO Gaming }; if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC && usbInterface.getInterfaceSubclass() == XB360_IFACE_SUBCLASS && (usbInterface.getInterfaceProtocol() == XB360_IFACE_PROTOCOL || usbInterface.getInterfaceProtocol() == XB360W_IFACE_PROTOCOL)) { int vendor_id = usbDevice.getVendorId(); for (int supportedVid : SUPPORTED_VENDORS) { if (vendor_id == supportedVid) { return true; } } } return false; } private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterface) { final int XB1_IFACE_SUBCLASS = 71; final int XB1_IFACE_PROTOCOL = 208; final int[] SUPPORTED_VENDORS = { 0x03f0, // HP 0x044f, // Thrustmaster 0x045e, // Microsoft 0x0738, // Mad Catz 0x0b05, // ASUS 0x0e6f, // PDP 0x0f0d, // Hori 0x10f5, // Turtle Beach 0x1532, // Razer Wildcat 0x20d6, // PowerA 0x24c6, // PowerA 0x2dc8, // 8BitDo 0x2e24, // Hyperkin 0x3537, // Gamesir }; if (usbInterface.getId() == 0 && usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC && usbInterface.getInterfaceSubclass() == XB1_IFACE_SUBCLASS && usbInterface.getInterfaceProtocol() == XB1_IFACE_PROTOCOL) { int vendor_id = usbDevice.getVendorId(); for (int supportedVid : SUPPORTED_VENDORS) { if (vendor_id == supportedVid) { return true; } } } return false; } private void handleUsbDeviceAttached(UsbDevice usbDevice) { connectHIDDeviceUSB(usbDevice); } private void handleUsbDeviceDetached(UsbDevice usbDevice) { List devices = new ArrayList(); for (HIDDevice device : mDevicesById.values()) { if (usbDevice.equals(device.getDevice())) { devices.add(device.getId()); } } for (int id : devices) { HIDDevice device = mDevicesById.get(id); mDevicesById.remove(id); device.shutdown(); HIDDeviceDisconnected(id); } } private void handleUsbDevicePermission(UsbDevice usbDevice, boolean permission_granted) { for (HIDDevice device : mDevicesById.values()) { if (usbDevice.equals(device.getDevice())) { boolean opened = false; if (permission_granted) { opened = device.open(); } HIDDeviceOpenResult(device.getId(), opened); } } } private void connectHIDDeviceUSB(UsbDevice usbDevice) { synchronized (this) { int interface_mask = 0; for (int interface_index = 0; interface_index < usbDevice.getInterfaceCount(); interface_index++) { UsbInterface usbInterface = usbDevice.getInterface(interface_index); if (isHIDDeviceInterface(usbDevice, usbInterface)) { // Check to see if we've already added this interface // This happens with the Xbox Series X controller which has a duplicate interface 0, which is inactive int interface_id = usbInterface.getId(); if ((interface_mask & (1 << interface_id)) != 0) { continue; } interface_mask |= (1 << interface_id); HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index); int id = device.getId(); mDevicesById.put(id, device); HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol()); } } } } private void initializeBluetooth() { Log.d(TAG, "Initializing Bluetooth"); if (Build.VERSION.SDK_INT >= 31 /* Android 12 */ && mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH_CONNECT"); return; } if (Build.VERSION.SDK_INT <= 30 /* Android 11.0 (R) */ && mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH"); return; } if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) || (Build.VERSION.SDK_INT < 18 /* Android 4.3 (JELLY_BEAN_MR2) */)) { Log.d(TAG, "Couldn't initialize Bluetooth, this version of Android does not support Bluetooth LE"); return; } // Find bonded bluetooth controllers and create SteamControllers for them mBluetoothManager = (BluetoothManager)mContext.getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { // This device doesn't support Bluetooth. return; } BluetoothAdapter btAdapter = mBluetoothManager.getAdapter(); if (btAdapter == null) { // This device has Bluetooth support in the codebase, but has no available adapters. return; } // Get our bonded devices. for (BluetoothDevice device : btAdapter.getBondedDevices()) { Log.d(TAG, "Bluetooth device available: " + device); if (isSteamController(device)) { connectBluetoothDevice(device); } } // NOTE: These don't work on Chromebooks, to my undying dismay. IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); mContext.registerReceiver(mBluetoothBroadcast, filter); if (mIsChromebook) { mHandler = new Handler(Looper.getMainLooper()); mLastBluetoothDevices = new ArrayList(); // final HIDDeviceManager finalThis = this; // mHandler.postDelayed(new Runnable() { // @Override // public void run() { // finalThis.chromebookConnectionHandler(); // } // }, 5000); } } private void shutdownBluetooth() { try { mContext.unregisterReceiver(mBluetoothBroadcast); } catch (Exception e) { // We may not have registered, that's okay } } // Chromebooks do not pass along ACTION_ACL_CONNECTED / ACTION_ACL_DISCONNECTED properly. // This function provides a sort of dummy version of that, watching for changes in the // connected devices and attempting to add controllers as things change. public void chromebookConnectionHandler() { if (!mIsChromebook) { return; } ArrayList disconnected = new ArrayList(); ArrayList connected = new ArrayList(); List currentConnected = mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT); for (BluetoothDevice bluetoothDevice : currentConnected) { if (!mLastBluetoothDevices.contains(bluetoothDevice)) { connected.add(bluetoothDevice); } } for (BluetoothDevice bluetoothDevice : mLastBluetoothDevices) { if (!currentConnected.contains(bluetoothDevice)) { disconnected.add(bluetoothDevice); } } mLastBluetoothDevices = currentConnected; for (BluetoothDevice bluetoothDevice : disconnected) { disconnectBluetoothDevice(bluetoothDevice); } for (BluetoothDevice bluetoothDevice : connected) { connectBluetoothDevice(bluetoothDevice); } final HIDDeviceManager finalThis = this; mHandler.postDelayed(new Runnable() { @Override public void run() { finalThis.chromebookConnectionHandler(); } }, 10000); } public boolean connectBluetoothDevice(BluetoothDevice bluetoothDevice) { Log.v(TAG, "connectBluetoothDevice device=" + bluetoothDevice); synchronized (this) { if (mBluetoothDevices.containsKey(bluetoothDevice)) { Log.v(TAG, "Steam controller with address " + bluetoothDevice + " already exists, attempting reconnect"); HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice); device.reconnect(); return false; } HIDDeviceBLESteamController device = new HIDDeviceBLESteamController(this, bluetoothDevice); int id = device.getId(); mBluetoothDevices.put(bluetoothDevice, device); mDevicesById.put(id, device); // The Steam Controller will mark itself connected once initialization is complete } return true; } public void disconnectBluetoothDevice(BluetoothDevice bluetoothDevice) { synchronized (this) { HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice); if (device == null) return; int id = device.getId(); mBluetoothDevices.remove(bluetoothDevice); mDevicesById.remove(id); device.shutdown(); HIDDeviceDisconnected(id); } } public boolean isSteamController(BluetoothDevice bluetoothDevice) { // Sanity check. If you pass in a null device, by definition it is never a Steam Controller. if (bluetoothDevice == null) { return false; } // If the device has no local name, we really don't want to try an equality check against it. if (bluetoothDevice.getName() == null) { return false; } return bluetoothDevice.getName().equals("SteamController") && ((bluetoothDevice.getType() & BluetoothDevice.DEVICE_TYPE_LE) != 0); } private void close() { shutdownUSB(); shutdownBluetooth(); synchronized (this) { for (HIDDevice device : mDevicesById.values()) { device.shutdown(); } mDevicesById.clear(); mBluetoothDevices.clear(); HIDDeviceReleaseCallback(); } } public void setFrozen(boolean frozen) { synchronized (this) { for (HIDDevice device : mDevicesById.values()) { device.setFrozen(frozen); } } } ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////// private HIDDevice getDevice(int id) { synchronized (this) { HIDDevice result = mDevicesById.get(id); if (result == null) { Log.v(TAG, "No device for id: " + id); Log.v(TAG, "Available devices: " + mDevicesById.keySet()); } return result; } } ////////////////////////////////////////////////////////////////////////////////////////////////////// ////////// JNI interface functions ////////////////////////////////////////////////////////////////////////////////////////////////////// public boolean initialize(boolean usb, boolean bluetooth) { Log.v(TAG, "initialize(" + usb + ", " + bluetooth + ")"); if (usb) { initializeUSB(); } if (bluetooth) { initializeBluetooth(); } return true; } public boolean openDevice(int deviceID) { Log.v(TAG, "openDevice deviceID=" + deviceID); HIDDevice device = getDevice(deviceID); if (device == null) { HIDDeviceDisconnected(deviceID); return false; } // Look to see if this is a USB device and we have permission to access it UsbDevice usbDevice = device.getDevice(); if (usbDevice != null && !mUsbManager.hasPermission(usbDevice)) { HIDDeviceOpenPending(deviceID); try { final int FLAG_MUTABLE = 0x02000000; // PendingIntent.FLAG_MUTABLE, but don't require SDK 31 int flags; if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) { flags = FLAG_MUTABLE; } else { flags = 0; } if (Build.VERSION.SDK_INT >= 33 /* Android 14.0 (U) */) { Intent intent = new Intent(HIDDeviceManager.ACTION_USB_PERMISSION); intent.setPackage(mContext.getPackageName()); mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, intent, flags)); } else { mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags)); } } catch (Exception e) { Log.v(TAG, "Couldn't request permission for USB device " + usbDevice); HIDDeviceOpenResult(deviceID, false); } return false; } try { return device.open(); } catch (Exception e) { Log.e(TAG, "Got exception: " + Log.getStackTraceString(e)); } return false; } public int sendOutputReport(int deviceID, byte[] report) { try { //Log.v(TAG, "sendOutputReport deviceID=" + deviceID + " length=" + report.length); HIDDevice device; device = getDevice(deviceID); if (device == null) { HIDDeviceDisconnected(deviceID); return -1; } return device.sendOutputReport(report); } catch (Exception e) { Log.e(TAG, "Got exception: " + Log.getStackTraceString(e)); } return -1; } public int sendFeatureReport(int deviceID, byte[] report) { try { //Log.v(TAG, "sendFeatureReport deviceID=" + deviceID + " length=" + report.length); HIDDevice device; device = getDevice(deviceID); if (device == null) { HIDDeviceDisconnected(deviceID); return -1; } return device.sendFeatureReport(report); } catch (Exception e) { Log.e(TAG, "Got exception: " + Log.getStackTraceString(e)); } return -1; } public boolean getFeatureReport(int deviceID, byte[] report) { try { //Log.v(TAG, "getFeatureReport deviceID=" + deviceID); HIDDevice device; device = getDevice(deviceID); if (device == null) { HIDDeviceDisconnected(deviceID); return false; } return device.getFeatureReport(report); } catch (Exception e) { Log.e(TAG, "Got exception: " + Log.getStackTraceString(e)); } return false; } public void closeDevice(int deviceID) { try { Log.v(TAG, "closeDevice deviceID=" + deviceID); HIDDevice device; device = getDevice(deviceID); if (device == null) { HIDDeviceDisconnected(deviceID); return; } device.close(); } catch (Exception e) { Log.e(TAG, "Got exception: " + Log.getStackTraceString(e)); } } ////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////// Native methods ////////////////////////////////////////////////////////////////////////////////////////////////////// private native void HIDDeviceRegisterCallback(); private native void HIDDeviceReleaseCallback(); native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol); native void HIDDeviceOpenPending(int deviceID); native void HIDDeviceOpenResult(int deviceID, boolean opened); native void HIDDeviceDisconnected(int deviceID); native void HIDDeviceInputReport(int deviceID, byte[] report); native void HIDDeviceFeatureReport(int deviceID, byte[] report); } ================================================ FILE: arch/android/project/app/src/main/java/org/libsdl/app/HIDDeviceUSB.java ================================================ package org.libsdl.app; import android.hardware.usb.*; import android.os.Build; import android.util.Log; import java.util.Arrays; class HIDDeviceUSB implements HIDDevice { private static final String TAG = "hidapi"; protected HIDDeviceManager mManager; protected UsbDevice mDevice; protected int mInterfaceIndex; protected int mInterface; protected int mDeviceId; protected UsbDeviceConnection mConnection; protected UsbEndpoint mInputEndpoint; protected UsbEndpoint mOutputEndpoint; protected InputThread mInputThread; protected boolean mRunning; protected boolean mFrozen; public HIDDeviceUSB(HIDDeviceManager manager, UsbDevice usbDevice, int interface_index) { mManager = manager; mDevice = usbDevice; mInterfaceIndex = interface_index; mInterface = mDevice.getInterface(mInterfaceIndex).getId(); mDeviceId = manager.getDeviceIDForIdentifier(getIdentifier()); mRunning = false; } public String getIdentifier() { return String.format("%s/%x/%x/%d", mDevice.getDeviceName(), mDevice.getVendorId(), mDevice.getProductId(), mInterfaceIndex); } @Override public int getId() { return mDeviceId; } @Override public int getVendorId() { return mDevice.getVendorId(); } @Override public int getProductId() { return mDevice.getProductId(); } @Override public String getSerialNumber() { String result = null; if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) { try { result = mDevice.getSerialNumber(); } catch (SecurityException exception) { //Log.w(TAG, "App permissions mean we cannot get serial number for device " + getDeviceName() + " message: " + exception.getMessage()); } } if (result == null) { result = ""; } return result; } @Override public int getVersion() { return 0; } @Override public String getManufacturerName() { String result = null; if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) { result = mDevice.getManufacturerName(); } if (result == null) { result = String.format("%x", getVendorId()); } return result; } @Override public String getProductName() { String result = null; if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) { result = mDevice.getProductName(); } if (result == null) { result = String.format("%x", getProductId()); } return result; } @Override public UsbDevice getDevice() { return mDevice; } public String getDeviceName() { return getManufacturerName() + " " + getProductName() + "(0x" + String.format("%x", getVendorId()) + "/0x" + String.format("%x", getProductId()) + ")"; } @Override public boolean open() { mConnection = mManager.getUSBManager().openDevice(mDevice); if (mConnection == null) { Log.w(TAG, "Unable to open USB device " + getDeviceName()); return false; } // Force claim our interface UsbInterface iface = mDevice.getInterface(mInterfaceIndex); if (!mConnection.claimInterface(iface, true)) { Log.w(TAG, "Failed to claim interfaces on USB device " + getDeviceName()); close(); return false; } // Find the endpoints for (int j = 0; j < iface.getEndpointCount(); j++) { UsbEndpoint endpt = iface.getEndpoint(j); switch (endpt.getDirection()) { case UsbConstants.USB_DIR_IN: if (mInputEndpoint == null) { mInputEndpoint = endpt; } break; case UsbConstants.USB_DIR_OUT: if (mOutputEndpoint == null) { mOutputEndpoint = endpt; } break; } } // Make sure the required endpoints were present if (mInputEndpoint == null || mOutputEndpoint == null) { Log.w(TAG, "Missing required endpoint on USB device " + getDeviceName()); close(); return false; } // Start listening for input mRunning = true; mInputThread = new InputThread(); mInputThread.start(); return true; } @Override public int sendFeatureReport(byte[] report) { int res = -1; int offset = 0; int length = report.length; boolean skipped_report_id = false; byte report_number = report[0]; if (report_number == 0x0) { ++offset; --length; skipped_report_id = true; } res = mConnection.controlTransfer( UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_OUT, 0x09/*HID set_report*/, (3/*HID feature*/ << 8) | report_number, mInterface, report, offset, length, 1000/*timeout millis*/); if (res < 0) { Log.w(TAG, "sendFeatureReport() returned " + res + " on device " + getDeviceName()); return -1; } if (skipped_report_id) { ++length; } return length; } @Override public int sendOutputReport(byte[] report) { int r = mConnection.bulkTransfer(mOutputEndpoint, report, report.length, 1000); if (r != report.length) { Log.w(TAG, "sendOutputReport() returned " + r + " on device " + getDeviceName()); } return r; } @Override public boolean getFeatureReport(byte[] report) { int res = -1; int offset = 0; int length = report.length; boolean skipped_report_id = false; byte report_number = report[0]; if (report_number == 0x0) { /* Offset the return buffer by 1, so that the report ID will remain in byte 0. */ ++offset; --length; skipped_report_id = true; } res = mConnection.controlTransfer( UsbConstants.USB_TYPE_CLASS | 0x01 /*RECIPIENT_INTERFACE*/ | UsbConstants.USB_DIR_IN, 0x01/*HID get_report*/, (3/*HID feature*/ << 8) | report_number, mInterface, report, offset, length, 1000/*timeout millis*/); if (res < 0) { Log.w(TAG, "getFeatureReport() returned " + res + " on device " + getDeviceName()); return false; } if (skipped_report_id) { ++res; ++length; } byte[] data; if (res == length) { data = report; } else { data = Arrays.copyOfRange(report, 0, res); } mManager.HIDDeviceFeatureReport(mDeviceId, data); return true; } @Override public void close() { mRunning = false; if (mInputThread != null) { while (mInputThread.isAlive()) { mInputThread.interrupt(); try { mInputThread.join(); } catch (InterruptedException e) { // Keep trying until we're done } } mInputThread = null; } if (mConnection != null) { UsbInterface iface = mDevice.getInterface(mInterfaceIndex); mConnection.releaseInterface(iface); mConnection.close(); mConnection = null; } } @Override public void shutdown() { close(); mManager = null; } @Override public void setFrozen(boolean frozen) { mFrozen = frozen; } protected class InputThread extends Thread { @Override public void run() { int packetSize = mInputEndpoint.getMaxPacketSize(); byte[] packet = new byte[packetSize]; while (mRunning) { int r; try { r = mConnection.bulkTransfer(mInputEndpoint, packet, packetSize, 1000); } catch (Exception e) { Log.v(TAG, "Exception in UsbDeviceConnection bulktransfer: " + e); break; } if (r < 0) { // Could be a timeout or an I/O error } if (r > 0) { byte[] data; if (r == packetSize) { data = packet; } else { data = Arrays.copyOfRange(packet, 0, r); } if (!mFrozen) { mManager.HIDDeviceInputReport(mDeviceId, data); } } } } } } ================================================ FILE: arch/android/project/app/src/main/java/org/libsdl/app/SDL.java ================================================ package org.libsdl.app; import android.content.Context; import java.lang.Class; import java.lang.reflect.Method; /** SDL library initialization */ public class SDL { // This function should be called first and sets up the native code // so it can call into the Java classes public static void setupJNI() { SDLActivity.nativeSetupJNI(); SDLAudioManager.nativeSetupJNI(); SDLControllerManager.nativeSetupJNI(); } // This function should be called each time the activity is started public static void initialize() { setContext(null); SDLActivity.initialize(); SDLAudioManager.initialize(); SDLControllerManager.initialize(); } // This function stores the current activity (SDL or not) public static void setContext(Context context) { SDLAudioManager.setContext(context); mContext = context; } public static Context getContext() { return mContext; } public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException { loadLibrary(libraryName, mContext); } public static void loadLibrary(String libraryName, Context context) throws UnsatisfiedLinkError, SecurityException, NullPointerException { if (libraryName == null) { throw new NullPointerException("No library name provided."); } try { // Let's see if we have ReLinker available in the project. This is necessary for // some projects that have huge numbers of local libraries bundled, and thus may // trip a bug in Android's native library loader which ReLinker works around. (If // loadLibrary works properly, ReLinker will simply use the normal Android method // internally.) // // To use ReLinker, just add it as a dependency. For more information, see // https://github.com/KeepSafe/ReLinker for ReLinker's repository. // Class relinkClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker"); Class relinkListenerClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener"); Class contextClass = context.getClassLoader().loadClass("android.content.Context"); Class stringClass = context.getClassLoader().loadClass("java.lang.String"); // Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if // they've changed during updates. Method forceMethod = relinkClass.getDeclaredMethod("force"); Object relinkInstance = forceMethod.invoke(null); Class relinkInstanceClass = relinkInstance.getClass(); // Actually load the library! Method loadMethod = relinkInstanceClass.getDeclaredMethod("loadLibrary", contextClass, stringClass, stringClass, relinkListenerClass); loadMethod.invoke(relinkInstance, context, libraryName, null, null); } catch (final Throwable e) { // Fall back try { System.loadLibrary(libraryName); } catch (final UnsatisfiedLinkError ule) { throw ule; } catch (final SecurityException se) { throw se; } } } protected static Context mContext; } ================================================ FILE: arch/android/project/app/src/main/java/org/libsdl/app/SDLActivity.java ================================================ package org.libsdl.app; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.UiModeManager; import android.content.ClipboardManager; import android.content.ClipData; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.hardware.Sensor; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.Editable; import android.text.InputType; import android.text.Selection; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseArray; import android.view.Display; import android.view.Gravity; import android.view.InputDevice; import android.view.KeyEvent; import android.view.PointerIcon; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import java.util.Hashtable; import java.util.Locale; /** SDL Activity */ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener { private static final String TAG = "SDL"; private static final int SDL_MAJOR_VERSION = 2; private static final int SDL_MINOR_VERSION = 30; private static final int SDL_MICRO_VERSION = 9; /* // Display InputType.SOURCE/CLASS of events and devices // // SDLActivity.debugSource(device.getSources(), "device[" + device.getName() + "]"); // SDLActivity.debugSource(event.getSource(), "event"); public static void debugSource(int sources, String prefix) { int s = sources; int s_copy = sources; String cls = ""; String src = ""; int tst = 0; int FLAG_TAINTED = 0x80000000; if ((s & InputDevice.SOURCE_CLASS_BUTTON) != 0) cls += " BUTTON"; if ((s & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) cls += " JOYSTICK"; if ((s & InputDevice.SOURCE_CLASS_POINTER) != 0) cls += " POINTER"; if ((s & InputDevice.SOURCE_CLASS_POSITION) != 0) cls += " POSITION"; if ((s & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) cls += " TRACKBALL"; int s2 = s_copy & ~InputDevice.SOURCE_ANY; // keep class bits s2 &= ~( InputDevice.SOURCE_CLASS_BUTTON | InputDevice.SOURCE_CLASS_JOYSTICK | InputDevice.SOURCE_CLASS_POINTER | InputDevice.SOURCE_CLASS_POSITION | InputDevice.SOURCE_CLASS_TRACKBALL); if (s2 != 0) cls += "Some_Unknown"; s2 = s_copy & InputDevice.SOURCE_ANY; // keep source only, no class; if (Build.VERSION.SDK_INT >= 23) { tst = InputDevice.SOURCE_BLUETOOTH_STYLUS; if ((s & tst) == tst) src += " BLUETOOTH_STYLUS"; s2 &= ~tst; } tst = InputDevice.SOURCE_DPAD; if ((s & tst) == tst) src += " DPAD"; s2 &= ~tst; tst = InputDevice.SOURCE_GAMEPAD; if ((s & tst) == tst) src += " GAMEPAD"; s2 &= ~tst; if (Build.VERSION.SDK_INT >= 21) { tst = InputDevice.SOURCE_HDMI; if ((s & tst) == tst) src += " HDMI"; s2 &= ~tst; } tst = InputDevice.SOURCE_JOYSTICK; if ((s & tst) == tst) src += " JOYSTICK"; s2 &= ~tst; tst = InputDevice.SOURCE_KEYBOARD; if ((s & tst) == tst) src += " KEYBOARD"; s2 &= ~tst; tst = InputDevice.SOURCE_MOUSE; if ((s & tst) == tst) src += " MOUSE"; s2 &= ~tst; if (Build.VERSION.SDK_INT >= 26) { tst = InputDevice.SOURCE_MOUSE_RELATIVE; if ((s & tst) == tst) src += " MOUSE_RELATIVE"; s2 &= ~tst; tst = InputDevice.SOURCE_ROTARY_ENCODER; if ((s & tst) == tst) src += " ROTARY_ENCODER"; s2 &= ~tst; } tst = InputDevice.SOURCE_STYLUS; if ((s & tst) == tst) src += " STYLUS"; s2 &= ~tst; tst = InputDevice.SOURCE_TOUCHPAD; if ((s & tst) == tst) src += " TOUCHPAD"; s2 &= ~tst; tst = InputDevice.SOURCE_TOUCHSCREEN; if ((s & tst) == tst) src += " TOUCHSCREEN"; s2 &= ~tst; if (Build.VERSION.SDK_INT >= 18) { tst = InputDevice.SOURCE_TOUCH_NAVIGATION; if ((s & tst) == tst) src += " TOUCH_NAVIGATION"; s2 &= ~tst; } tst = InputDevice.SOURCE_TRACKBALL; if ((s & tst) == tst) src += " TRACKBALL"; s2 &= ~tst; tst = InputDevice.SOURCE_ANY; if ((s & tst) == tst) src += " ANY"; s2 &= ~tst; if (s == FLAG_TAINTED) src += " FLAG_TAINTED"; s2 &= ~FLAG_TAINTED; if (s2 != 0) src += " Some_Unknown"; Log.v(TAG, prefix + "int=" + s_copy + " CLASS={" + cls + " } source(s):" + src); } */ public static boolean mIsResumedCalled, mHasFocus; public static final boolean mHasMultiWindow = (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */); // Cursor types // private static final int SDL_SYSTEM_CURSOR_NONE = -1; private static final int SDL_SYSTEM_CURSOR_ARROW = 0; private static final int SDL_SYSTEM_CURSOR_IBEAM = 1; private static final int SDL_SYSTEM_CURSOR_WAIT = 2; private static final int SDL_SYSTEM_CURSOR_CROSSHAIR = 3; private static final int SDL_SYSTEM_CURSOR_WAITARROW = 4; private static final int SDL_SYSTEM_CURSOR_SIZENWSE = 5; private static final int SDL_SYSTEM_CURSOR_SIZENESW = 6; private static final int SDL_SYSTEM_CURSOR_SIZEWE = 7; private static final int SDL_SYSTEM_CURSOR_SIZENS = 8; private static final int SDL_SYSTEM_CURSOR_SIZEALL = 9; private static final int SDL_SYSTEM_CURSOR_NO = 10; private static final int SDL_SYSTEM_CURSOR_HAND = 11; protected static final int SDL_ORIENTATION_UNKNOWN = 0; protected static final int SDL_ORIENTATION_LANDSCAPE = 1; protected static final int SDL_ORIENTATION_LANDSCAPE_FLIPPED = 2; protected static final int SDL_ORIENTATION_PORTRAIT = 3; protected static final int SDL_ORIENTATION_PORTRAIT_FLIPPED = 4; protected static int mCurrentOrientation; protected static Locale mCurrentLocale; // Handle the state of the native layer public enum NativeState { INIT, RESUMED, PAUSED } public static NativeState mNextNativeState; public static NativeState mCurrentNativeState; /** If shared libraries (e.g. SDL or the native application) could not be loaded. */ public static boolean mBrokenLibraries = true; // Main components protected static SDLActivity mSingleton; protected static SDLSurface mSurface; protected static DummyEdit mTextEdit; protected static boolean mScreenKeyboardShown; protected static ViewGroup mLayout; protected static SDLClipboardHandler mClipboardHandler; protected static Hashtable mCursors; protected static int mLastCursorID; protected static SDLGenericMotionListener_API12 mMotionListener; protected static HIDDeviceManager mHIDDeviceManager; // This is what SDL runs in. It invokes SDL_main(), eventually protected static Thread mSDLThread; protected static SDLGenericMotionListener_API12 getMotionListener() { if (mMotionListener == null) { if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) { mMotionListener = new SDLGenericMotionListener_API26(); } else if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) { mMotionListener = new SDLGenericMotionListener_API24(); } else { mMotionListener = new SDLGenericMotionListener_API12(); } } return mMotionListener; } /** * This method returns the name of the shared object with the application entry point * It can be overridden by derived classes. */ protected String getMainSharedObject() { String library; String[] libraries = SDLActivity.mSingleton.getLibraries(); if (libraries.length > 0) { library = "lib" + libraries[libraries.length - 1] + ".so"; } else { library = "libmain.so"; } return getContext().getApplicationInfo().nativeLibraryDir + "/" + library; } /** * This method returns the name of the application entry point * It can be overridden by derived classes. */ protected String getMainFunction() { return "SDL_main"; } /** * This method is called by SDL before loading the native shared libraries. * It can be overridden to provide names of shared libraries to be loaded. * The default implementation returns the defaults. It never returns null. * An array returned by a new implementation must at least contain "SDL2". * Also keep in mind that the order the libraries are loaded may matter. * @return names of shared libraries to be loaded (e.g. "SDL2", "main"). */ protected String[] getLibraries() { return new String[] { "SDL2", // "SDL2_image", // "SDL2_mixer", // "SDL2_net", // "SDL2_ttf", "main" }; } // Load the .so public void loadLibraries() { for (String lib : getLibraries()) { SDL.loadLibrary(lib, this); } } /** * This method is called by SDL before starting the native application thread. * It can be overridden to provide the arguments after the application name. * The default implementation returns an empty array. It never returns null. * @return arguments for the native application. */ protected String[] getArguments() { return new String[0]; } public static void initialize() { // The static nature of the singleton and Android quirkyness force us to initialize everything here // Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values mSingleton = null; mSurface = null; mTextEdit = null; mLayout = null; mClipboardHandler = null; mCursors = new Hashtable(); mLastCursorID = 0; mSDLThread = null; mIsResumedCalled = false; mHasFocus = true; mNextNativeState = NativeState.INIT; mCurrentNativeState = NativeState.INIT; } protected SDLSurface createSDLSurface(Context context) { return new SDLSurface(context); } // Setup @Override protected void onCreate(Bundle savedInstanceState) { Log.v(TAG, "Device: " + Build.DEVICE); Log.v(TAG, "Model: " + Build.MODEL); Log.v(TAG, "onCreate()"); super.onCreate(savedInstanceState); try { Thread.currentThread().setName("SDLActivity"); } catch (Exception e) { Log.v(TAG, "modify thread properties failed " + e.toString()); } // Load shared libraries String errorMsgBrokenLib = ""; try { loadLibraries(); mBrokenLibraries = false; /* success */ } catch(UnsatisfiedLinkError e) { System.err.println(e.getMessage()); mBrokenLibraries = true; errorMsgBrokenLib = e.getMessage(); } catch(Exception e) { System.err.println(e.getMessage()); mBrokenLibraries = true; errorMsgBrokenLib = e.getMessage(); } if (!mBrokenLibraries) { String expected_version = String.valueOf(SDL_MAJOR_VERSION) + "." + String.valueOf(SDL_MINOR_VERSION) + "." + String.valueOf(SDL_MICRO_VERSION); String version = nativeGetVersion(); if (!version.equals(expected_version)) { mBrokenLibraries = true; errorMsgBrokenLib = "SDL C/Java version mismatch (expected " + expected_version + ", got " + version + ")"; } } if (mBrokenLibraries) { mSingleton = this; AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this); dlgAlert.setMessage("An error occurred while trying to start the application. Please try again and/or reinstall." + System.getProperty("line.separator") + System.getProperty("line.separator") + "Error: " + errorMsgBrokenLib); dlgAlert.setTitle("SDL Error"); dlgAlert.setPositiveButton("Exit", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog,int id) { // if this button is clicked, close current activity SDLActivity.mSingleton.finish(); } }); dlgAlert.setCancelable(false); dlgAlert.create().show(); return; } // Set up JNI SDL.setupJNI(); // Initialize state SDL.initialize(); // So we can call stuff from static callbacks mSingleton = this; SDL.setContext(this); mClipboardHandler = new SDLClipboardHandler(); mHIDDeviceManager = HIDDeviceManager.acquire(this); // Set up the surface mSurface = createSDLSurface(this); mLayout = new RelativeLayout(this); mLayout.addView(mSurface); // Get our current screen orientation and pass it down. mCurrentOrientation = SDLActivity.getCurrentOrientation(); // Only record current orientation SDLActivity.onNativeOrientationChanged(mCurrentOrientation); try { if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) { mCurrentLocale = getContext().getResources().getConfiguration().locale; } else { mCurrentLocale = getContext().getResources().getConfiguration().getLocales().get(0); } } catch(Exception ignored) { } setContentView(mLayout); setWindowStyle(false); getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this); // Get filename from "Open with" of another application Intent intent = getIntent(); if (intent != null && intent.getData() != null) { String filename = intent.getData().getPath(); if (filename != null) { Log.v(TAG, "Got filename: " + filename); SDLActivity.onNativeDropFile(filename); } } } protected void pauseNativeThread() { mNextNativeState = NativeState.PAUSED; mIsResumedCalled = false; if (SDLActivity.mBrokenLibraries) { return; } SDLActivity.handleNativeState(); } protected void resumeNativeThread() { mNextNativeState = NativeState.RESUMED; mIsResumedCalled = true; if (SDLActivity.mBrokenLibraries) { return; } SDLActivity.handleNativeState(); } // Events @Override protected void onPause() { Log.v(TAG, "onPause()"); super.onPause(); if (mHIDDeviceManager != null) { mHIDDeviceManager.setFrozen(true); } if (!mHasMultiWindow) { pauseNativeThread(); } } @Override protected void onResume() { Log.v(TAG, "onResume()"); super.onResume(); if (mHIDDeviceManager != null) { mHIDDeviceManager.setFrozen(false); } if (!mHasMultiWindow) { resumeNativeThread(); } } @Override protected void onStop() { Log.v(TAG, "onStop()"); super.onStop(); if (mHasMultiWindow) { pauseNativeThread(); } } @Override protected void onStart() { Log.v(TAG, "onStart()"); super.onStart(); if (mHasMultiWindow) { resumeNativeThread(); } } public static int getCurrentOrientation() { int result = SDL_ORIENTATION_UNKNOWN; Activity activity = (Activity)getContext(); if (activity == null) { return result; } Display display = activity.getWindowManager().getDefaultDisplay(); switch (display.getRotation()) { case Surface.ROTATION_0: result = SDL_ORIENTATION_PORTRAIT; break; case Surface.ROTATION_90: result = SDL_ORIENTATION_LANDSCAPE; break; case Surface.ROTATION_180: result = SDL_ORIENTATION_PORTRAIT_FLIPPED; break; case Surface.ROTATION_270: result = SDL_ORIENTATION_LANDSCAPE_FLIPPED; break; } return result; } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); Log.v(TAG, "onWindowFocusChanged(): " + hasFocus); if (SDLActivity.mBrokenLibraries) { return; } mHasFocus = hasFocus; if (hasFocus) { mNextNativeState = NativeState.RESUMED; SDLActivity.getMotionListener().reclaimRelativeMouseModeIfNeeded(); SDLActivity.handleNativeState(); nativeFocusChanged(true); } else { nativeFocusChanged(false); if (!mHasMultiWindow) { mNextNativeState = NativeState.PAUSED; SDLActivity.handleNativeState(); } } } @Override public void onLowMemory() { Log.v(TAG, "onLowMemory()"); super.onLowMemory(); if (SDLActivity.mBrokenLibraries) { return; } SDLActivity.nativeLowMemory(); } @Override public void onConfigurationChanged(Configuration newConfig) { Log.v(TAG, "onConfigurationChanged()"); super.onConfigurationChanged(newConfig); if (SDLActivity.mBrokenLibraries) { return; } if (mCurrentLocale == null || !mCurrentLocale.equals(newConfig.locale)) { mCurrentLocale = newConfig.locale; SDLActivity.onNativeLocaleChanged(); } } @Override protected void onDestroy() { Log.v(TAG, "onDestroy()"); if (mHIDDeviceManager != null) { HIDDeviceManager.release(mHIDDeviceManager); mHIDDeviceManager = null; } SDLAudioManager.release(this); if (SDLActivity.mBrokenLibraries) { super.onDestroy(); return; } if (SDLActivity.mSDLThread != null) { // Send Quit event to "SDLThread" thread SDLActivity.nativeSendQuit(); // Wait for "SDLThread" thread to end try { SDLActivity.mSDLThread.join(); } catch(Exception e) { Log.v(TAG, "Problem stopping SDLThread: " + e); } } SDLActivity.nativeQuit(); super.onDestroy(); } @Override public void onBackPressed() { // Check if we want to block the back button in case of mouse right click. // // If we do, the normal hardware back button will no longer work and people have to use home, // but the mouse right click will work. // boolean trapBack = SDLActivity.nativeGetHintBoolean("SDL_ANDROID_TRAP_BACK_BUTTON", false); if (trapBack) { // Exit and let the mouse handler handle this button (if appropriate) return; } // Default system back button behavior. if (!isFinishing()) { super.onBackPressed(); } } // Called by JNI from SDL. public static void manualBackButton() { mSingleton.pressBackButton(); } // Used to get us onto the activity's main thread public void pressBackButton() { runOnUiThread(new Runnable() { @Override public void run() { if (!SDLActivity.this.isFinishing()) { SDLActivity.this.superOnBackPressed(); } } }); } // Used to access the system back behavior. public void superOnBackPressed() { super.onBackPressed(); } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (SDLActivity.mBrokenLibraries) { return false; } int keyCode = event.getKeyCode(); // Ignore certain special keys so they're handled by Android if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_CAMERA || keyCode == KeyEvent.KEYCODE_ZOOM_IN || /* API 11 */ keyCode == KeyEvent.KEYCODE_ZOOM_OUT /* API 11 */ ) { return false; } return super.dispatchKeyEvent(event); } /* Transition to next state */ public static void handleNativeState() { if (mNextNativeState == mCurrentNativeState) { // Already in same state, discard. return; } // Try a transition to init state if (mNextNativeState == NativeState.INIT) { mCurrentNativeState = mNextNativeState; return; } // Try a transition to paused state if (mNextNativeState == NativeState.PAUSED) { if (mSDLThread != null) { nativePause(); } if (mSurface != null) { mSurface.handlePause(); } mCurrentNativeState = mNextNativeState; return; } // Try a transition to resumed state if (mNextNativeState == NativeState.RESUMED) { if (mSurface.mIsSurfaceReady && mHasFocus && mIsResumedCalled) { if (mSDLThread == null) { // This is the entry point to the C app. // Start up the C app thread and enable sensor input for the first time // FIXME: Why aren't we enabling sensor input at start? mSDLThread = new Thread(new SDLMain(), "SDLThread"); mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true); mSDLThread.start(); // No nativeResume(), don't signal Android_ResumeSem } else { nativeResume(); } mSurface.handleResume(); mCurrentNativeState = mNextNativeState; } } } // Messages from the SDLMain thread static final int COMMAND_CHANGE_TITLE = 1; static final int COMMAND_CHANGE_WINDOW_STYLE = 2; static final int COMMAND_TEXTEDIT_HIDE = 3; static final int COMMAND_SET_KEEP_SCREEN_ON = 5; protected static final int COMMAND_USER = 0x8000; protected static boolean mFullscreenModeActive; /** * This method is called by SDL if SDL did not handle a message itself. * This happens if a received message contains an unsupported command. * Method can be overwritten to handle Messages in a different class. * @param command the command of the message. * @param param the parameter of the message. May be null. * @return if the message was handled in overridden method. */ protected boolean onUnhandledMessage(int command, Object param) { return false; } /** * A Handler class for Messages from native SDL applications. * It uses current Activities as target (e.g. for the title). * static to prevent implicit references to enclosing object. */ protected static class SDLCommandHandler extends Handler { @Override public void handleMessage(Message msg) { Context context = SDL.getContext(); if (context == null) { Log.e(TAG, "error handling message, getContext() returned null"); return; } switch (msg.arg1) { case COMMAND_CHANGE_TITLE: if (context instanceof Activity) { ((Activity) context).setTitle((String)msg.obj); } else { Log.e(TAG, "error handling message, getContext() returned no Activity"); } break; case COMMAND_CHANGE_WINDOW_STYLE: if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) { if (context instanceof Activity) { Window window = ((Activity) context).getWindow(); if (window != null) { if ((msg.obj instanceof Integer) && ((Integer) msg.obj != 0)) { int flags = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE; window.getDecorView().setSystemUiVisibility(flags); window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); SDLActivity.mFullscreenModeActive = true; } else { int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE; window.getDecorView().setSystemUiVisibility(flags); window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); SDLActivity.mFullscreenModeActive = false; } } } else { Log.e(TAG, "error handling message, getContext() returned no Activity"); } } break; case COMMAND_TEXTEDIT_HIDE: if (mTextEdit != null) { // Note: On some devices setting view to GONE creates a flicker in landscape. // Setting the View's sizes to 0 is similar to GONE but without the flicker. // The sizes will be set to useful values when the keyboard is shown again. mTextEdit.setLayoutParams(new RelativeLayout.LayoutParams(0, 0)); InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0); mScreenKeyboardShown = false; mSurface.requestFocus(); } break; case COMMAND_SET_KEEP_SCREEN_ON: { if (context instanceof Activity) { Window window = ((Activity) context).getWindow(); if (window != null) { if ((msg.obj instanceof Integer) && ((Integer) msg.obj != 0)) { window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } else { window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } } } break; } default: if ((context instanceof SDLActivity) && !((SDLActivity) context).onUnhandledMessage(msg.arg1, msg.obj)) { Log.e(TAG, "error handling message, command is " + msg.arg1); } } } } // Handler for the messages Handler commandHandler = new SDLCommandHandler(); // Send a message from the SDLMain thread boolean sendCommand(int command, Object data) { Message msg = commandHandler.obtainMessage(); msg.arg1 = command; msg.obj = data; boolean result = commandHandler.sendMessage(msg); if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) { if (command == COMMAND_CHANGE_WINDOW_STYLE) { // Ensure we don't return until the resize has actually happened, // or 500ms have passed. boolean bShouldWait = false; if (data instanceof Integer) { // Let's figure out if we're already laid out fullscreen or not. Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); DisplayMetrics realMetrics = new DisplayMetrics(); display.getRealMetrics(realMetrics); boolean bFullscreenLayout = ((realMetrics.widthPixels == mSurface.getWidth()) && (realMetrics.heightPixels == mSurface.getHeight())); if ((Integer) data == 1) { // If we aren't laid out fullscreen or actively in fullscreen mode already, we're going // to change size and should wait for surfaceChanged() before we return, so the size // is right back in native code. If we're already laid out fullscreen, though, we're // not going to change size even if we change decor modes, so we shouldn't wait for // surfaceChanged() -- which may not even happen -- and should return immediately. bShouldWait = !bFullscreenLayout; } else { // If we're laid out fullscreen (even if the status bar and nav bar are present), // or are actively in fullscreen, we're going to change size and should wait for // surfaceChanged before we return, so the size is right back in native code. bShouldWait = bFullscreenLayout; } } if (bShouldWait && (SDLActivity.getContext() != null)) { // We'll wait for the surfaceChanged() method, which will notify us // when called. That way, we know our current size is really the // size we need, instead of grabbing a size that's still got // the navigation and/or status bars before they're hidden. // // We'll wait for up to half a second, because some devices // take a surprisingly long time for the surface resize, but // then we'll just give up and return. // synchronized (SDLActivity.getContext()) { try { SDLActivity.getContext().wait(500); } catch (InterruptedException ie) { ie.printStackTrace(); } } } } } return result; } // C functions we call public static native String nativeGetVersion(); public static native int nativeSetupJNI(); public static native int nativeRunMain(String library, String function, Object arguments); public static native void nativeLowMemory(); public static native void nativeSendQuit(); public static native void nativeQuit(); public static native void nativePause(); public static native void nativeResume(); public static native void nativeFocusChanged(boolean hasFocus); public static native void onNativeDropFile(String filename); public static native void nativeSetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float rate); public static native void onNativeResize(); public static native void onNativeKeyDown(int keycode); public static native void onNativeKeyUp(int keycode); public static native boolean onNativeSoftReturnKey(); public static native void onNativeKeyboardFocusLost(); public static native void onNativeMouse(int button, int action, float x, float y, boolean relative); public static native void onNativeTouch(int touchDevId, int pointerFingerId, int action, float x, float y, float p); public static native void onNativeAccel(float x, float y, float z); public static native void onNativeClipboardChanged(); public static native void onNativeSurfaceCreated(); public static native void onNativeSurfaceChanged(); public static native void onNativeSurfaceDestroyed(); public static native String nativeGetHint(String name); public static native boolean nativeGetHintBoolean(String name, boolean default_value); public static native void nativeSetenv(String name, String value); public static native void onNativeOrientationChanged(int orientation); public static native void nativeAddTouch(int touchId, String name); public static native void nativePermissionResult(int requestCode, boolean result); public static native void onNativeLocaleChanged(); /** * This method is called by SDL using JNI. */ public static boolean setActivityTitle(String title) { // Called from SDLMain() thread and can't directly affect the view return mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title); } /** * This method is called by SDL using JNI. */ public static void setWindowStyle(boolean fullscreen) { // Called from SDLMain() thread and can't directly affect the view mSingleton.sendCommand(COMMAND_CHANGE_WINDOW_STYLE, fullscreen ? 1 : 0); } /** * This method is called by SDL using JNI. * This is a static method for JNI convenience, it calls a non-static method * so that is can be overridden */ public static void setOrientation(int w, int h, boolean resizable, String hint) { if (mSingleton != null) { mSingleton.setOrientationBis(w, h, resizable, hint); } } /** * This can be overridden */ public void setOrientationBis(int w, int h, boolean resizable, String hint) { int orientation_landscape = -1; int orientation_portrait = -1; /* If set, hint "explicitly controls which UI orientations are allowed". */ if (hint.contains("LandscapeRight") && hint.contains("LandscapeLeft")) { orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; } else if (hint.contains("LandscapeLeft")) { orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; } else if (hint.contains("LandscapeRight")) { orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; } /* exact match to 'Portrait' to distinguish with PortraitUpsideDown */ boolean contains_Portrait = hint.contains("Portrait ") || hint.endsWith("Portrait"); if (contains_Portrait && hint.contains("PortraitUpsideDown")) { orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; } else if (contains_Portrait) { orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; } else if (hint.contains("PortraitUpsideDown")) { orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; } boolean is_landscape_allowed = (orientation_landscape != -1); boolean is_portrait_allowed = (orientation_portrait != -1); int req; /* Requested orientation */ /* No valid hint, nothing is explicitly allowed */ if (!is_portrait_allowed && !is_landscape_allowed) { if (resizable) { /* All orientations are allowed, respecting user orientation lock setting */ req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER; } else { /* Fixed window and nothing specified. Get orientation from w/h of created window */ req = (w > h ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); } } else { /* At least one orientation is allowed */ if (resizable) { if (is_portrait_allowed && is_landscape_allowed) { /* hint allows both landscape and portrait, promote to full user */ req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER; } else { /* Use the only one allowed "orientation" */ req = (is_landscape_allowed ? orientation_landscape : orientation_portrait); } } else { /* Fixed window and both orientations are allowed. Choose one. */ if (is_portrait_allowed && is_landscape_allowed) { req = (w > h ? orientation_landscape : orientation_portrait); } else { /* Use the only one allowed "orientation" */ req = (is_landscape_allowed ? orientation_landscape : orientation_portrait); } } } Log.v(TAG, "setOrientation() requestedOrientation=" + req + " width=" + w +" height="+ h +" resizable=" + resizable + " hint=" + hint); mSingleton.setRequestedOrientation(req); } /** * This method is called by SDL using JNI. */ public static void minimizeWindow() { if (mSingleton == null) { return; } Intent startMain = new Intent(Intent.ACTION_MAIN); startMain.addCategory(Intent.CATEGORY_HOME); startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mSingleton.startActivity(startMain); } /** * This method is called by SDL using JNI. */ public static boolean shouldMinimizeOnFocusLoss() { /* if (Build.VERSION.SDK_INT >= 24) { if (mSingleton == null) { return true; } if (mSingleton.isInMultiWindowMode()) { return false; } if (mSingleton.isInPictureInPictureMode()) { return false; } } return true; */ return false; } /** * This method is called by SDL using JNI. */ public static boolean isScreenKeyboardShown() { if (mTextEdit == null) { return false; } if (!mScreenKeyboardShown) { return false; } InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); return imm.isAcceptingText(); } /** * This method is called by SDL using JNI. */ public static boolean supportsRelativeMouse() { // DeX mode in Samsung Experience 9.0 and earlier doesn't support relative mice properly under // Android 7 APIs, and simply returns no data under Android 8 APIs. // // This is fixed in Samsung Experience 9.5, which corresponds to Android 8.1.0, and // thus SDK version 27. If we are in DeX mode and not API 27 or higher, as a result, // we should stick to relative mode. // if (Build.VERSION.SDK_INT < 27 /* Android 8.1 (O_MR1) */ && isDeXMode()) { return false; } return SDLActivity.getMotionListener().supportsRelativeMouse(); } /** * This method is called by SDL using JNI. */ public static boolean setRelativeMouseEnabled(boolean enabled) { if (enabled && !supportsRelativeMouse()) { return false; } return SDLActivity.getMotionListener().setRelativeMouseEnabled(enabled); } /** * This method is called by SDL using JNI. */ public static boolean sendMessage(int command, int param) { if (mSingleton == null) { return false; } return mSingleton.sendCommand(command, param); } /** * This method is called by SDL using JNI. */ public static Context getContext() { return SDL.getContext(); } /** * This method is called by SDL using JNI. */ public static boolean isAndroidTV() { UiModeManager uiModeManager = (UiModeManager) getContext().getSystemService(UI_MODE_SERVICE); if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) { return true; } if (Build.MANUFACTURER.equals("MINIX") && Build.MODEL.equals("NEO-U1")) { return true; } if (Build.MANUFACTURER.equals("Amlogic") && Build.MODEL.equals("X96-W")) { return true; } return Build.MANUFACTURER.equals("Amlogic") && Build.MODEL.startsWith("TV"); } public static double getDiagonal() { DisplayMetrics metrics = new DisplayMetrics(); Activity activity = (Activity)getContext(); if (activity == null) { return 0.0; } activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); double dWidthInches = metrics.widthPixels / (double)metrics.xdpi; double dHeightInches = metrics.heightPixels / (double)metrics.ydpi; return Math.sqrt((dWidthInches * dWidthInches) + (dHeightInches * dHeightInches)); } /** * This method is called by SDL using JNI. */ public static boolean isTablet() { // If our diagonal size is seven inches or greater, we consider ourselves a tablet. return (getDiagonal() >= 7.0); } /** * This method is called by SDL using JNI. */ public static boolean isChromebook() { if (getContext() == null) { return false; } return getContext().getPackageManager().hasSystemFeature("org.chromium.arc.device_management"); } /** * This method is called by SDL using JNI. */ public static boolean isDeXMode() { if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) { return false; } try { final Configuration config = getContext().getResources().getConfiguration(); final Class configClass = config.getClass(); return configClass.getField("SEM_DESKTOP_MODE_ENABLED").getInt(configClass) == configClass.getField("semDesktopModeEnabled").getInt(config); } catch(Exception ignored) { return false; } } /** * This method is called by SDL using JNI. */ public static DisplayMetrics getDisplayDPI() { return getContext().getResources().getDisplayMetrics(); } /** * This method is called by SDL using JNI. */ public static boolean getManifestEnvironmentVariables() { try { if (getContext() == null) { return false; } ApplicationInfo applicationInfo = getContext().getPackageManager().getApplicationInfo(getContext().getPackageName(), PackageManager.GET_META_DATA); Bundle bundle = applicationInfo.metaData; if (bundle == null) { return false; } String prefix = "SDL_ENV."; final int trimLength = prefix.length(); for (String key : bundle.keySet()) { if (key.startsWith(prefix)) { String name = key.substring(trimLength); String value = bundle.get(key).toString(); nativeSetenv(name, value); } } /* environment variables set! */ return true; } catch (Exception e) { Log.v(TAG, "exception " + e.toString()); } return false; } // This method is called by SDLControllerManager's API 26 Generic Motion Handler. public static View getContentView() { return mLayout; } static class ShowTextInputTask implements Runnable { /* * This is used to regulate the pan&scan method to have some offset from * the bottom edge of the input region and the top edge of an input * method (soft keyboard) */ static final int HEIGHT_PADDING = 15; public int x, y, w, h; public ShowTextInputTask(int x, int y, int w, int h) { this.x = x; this.y = y; this.w = w; this.h = h; /* Minimum size of 1 pixel, so it takes focus. */ if (this.w <= 0) { this.w = 1; } if (this.h + HEIGHT_PADDING <= 0) { this.h = 1 - HEIGHT_PADDING; } } @Override public void run() { RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(w, h + HEIGHT_PADDING); params.leftMargin = x; params.topMargin = y; if (mTextEdit == null) { mTextEdit = new DummyEdit(SDL.getContext()); mLayout.addView(mTextEdit, params); } else { mTextEdit.setLayoutParams(params); } mTextEdit.setVisibility(View.VISIBLE); mTextEdit.requestFocus(); InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(mTextEdit, 0); mScreenKeyboardShown = true; } } /** * This method is called by SDL using JNI. */ public static boolean showTextInput(int x, int y, int w, int h) { // Transfer the task to the main thread as a Runnable return mSingleton.commandHandler.post(new ShowTextInputTask(x, y, w, h)); } public static boolean isTextInputEvent(KeyEvent event) { // Key pressed with Ctrl should be sent as SDL_KEYDOWN/SDL_KEYUP and not SDL_TEXTINPUT if (event.isCtrlPressed()) { return false; } return event.isPrintingKey() || event.getKeyCode() == KeyEvent.KEYCODE_SPACE; } public static boolean handleKeyEvent(View v, int keyCode, KeyEvent event, InputConnection ic) { int deviceId = event.getDeviceId(); int source = event.getSource(); if (source == InputDevice.SOURCE_UNKNOWN) { InputDevice device = InputDevice.getDevice(deviceId); if (device != null) { source = device.getSources(); } } // if (event.getAction() == KeyEvent.ACTION_DOWN) { // Log.v("SDL", "key down: " + keyCode + ", deviceId = " + deviceId + ", source = " + source); // } else if (event.getAction() == KeyEvent.ACTION_UP) { // Log.v("SDL", "key up: " + keyCode + ", deviceId = " + deviceId + ", source = " + source); // } // Dispatch the different events depending on where they come from // Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD // So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD // // Furthermore, it's possible a game controller has SOURCE_KEYBOARD and // SOURCE_JOYSTICK, while its key events arrive from the keyboard source // So, retrieve the device itself and check all of its sources if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) { // Note that we process events with specific key codes here if (event.getAction() == KeyEvent.ACTION_DOWN) { if (SDLControllerManager.onNativePadDown(deviceId, keyCode) == 0) { return true; } } else if (event.getAction() == KeyEvent.ACTION_UP) { if (SDLControllerManager.onNativePadUp(deviceId, keyCode) == 0) { return true; } } } if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) { // on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses // they are ignored here because sending them as mouse input to SDL is messy if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) { switch (event.getAction()) { case KeyEvent.ACTION_DOWN: case KeyEvent.ACTION_UP: // mark the event as handled or it will be handled by system // handling KEYCODE_BACK by system will call onBackPressed() return true; } } } if (event.getAction() == KeyEvent.ACTION_DOWN) { if (isTextInputEvent(event)) { if (ic != null) { ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1); } else { SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1); } } onNativeKeyDown(keyCode); return true; } else if (event.getAction() == KeyEvent.ACTION_UP) { onNativeKeyUp(keyCode); return true; } return false; } /** * This method is called by SDL using JNI. */ public static Surface getNativeSurface() { if (SDLActivity.mSurface == null) { return null; } return SDLActivity.mSurface.getNativeSurface(); } // Input /** * This method is called by SDL using JNI. */ public static void initTouch() { int[] ids = InputDevice.getDeviceIds(); for (int id : ids) { InputDevice device = InputDevice.getDevice(id); /* Allow SOURCE_TOUCHSCREEN and also Virtual InputDevices because they can send TOUCHSCREEN events */ if (device != null && ((device.getSources() & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN || device.isVirtual())) { int touchDevId = device.getId(); /* * Prevent id to be -1, since it's used in SDL internal for synthetic events * Appears when using Android emulator, eg: * adb shell input mouse tap 100 100 * adb shell input touchscreen tap 100 100 */ if (touchDevId < 0) { touchDevId -= 1; } nativeAddTouch(touchDevId, device.getName()); } } } // Messagebox /** Result of current messagebox. Also used for blocking the calling thread. */ protected final int[] messageboxSelection = new int[1]; /** * This method is called by SDL using JNI. * Shows the messagebox from UI thread and block calling thread. * buttonFlags, buttonIds and buttonTexts must have same length. * @param buttonFlags array containing flags for every button. * @param buttonIds array containing id for every button. * @param buttonTexts array containing text for every button. * @param colors null for default or array of length 5 containing colors. * @return button id or -1. */ public int messageboxShowMessageBox( final int flags, final String title, final String message, final int[] buttonFlags, final int[] buttonIds, final String[] buttonTexts, final int[] colors) { messageboxSelection[0] = -1; // sanity checks if ((buttonFlags.length != buttonIds.length) && (buttonIds.length != buttonTexts.length)) { return -1; // implementation broken } // collect arguments for Dialog final Bundle args = new Bundle(); args.putInt("flags", flags); args.putString("title", title); args.putString("message", message); args.putIntArray("buttonFlags", buttonFlags); args.putIntArray("buttonIds", buttonIds); args.putStringArray("buttonTexts", buttonTexts); args.putIntArray("colors", colors); // trigger Dialog creation on UI thread runOnUiThread(new Runnable() { @Override public void run() { messageboxCreateAndShow(args); } }); // block the calling thread synchronized (messageboxSelection) { try { messageboxSelection.wait(); } catch (InterruptedException ex) { ex.printStackTrace(); return -1; } } // return selected value return messageboxSelection[0]; } protected void messageboxCreateAndShow(Bundle args) { // TODO set values from "flags" to messagebox dialog // get colors int[] colors = args.getIntArray("colors"); int backgroundColor; int textColor; int buttonBorderColor; int buttonBackgroundColor; int buttonSelectedColor; if (colors != null) { int i = -1; backgroundColor = colors[++i]; textColor = colors[++i]; buttonBorderColor = colors[++i]; buttonBackgroundColor = colors[++i]; buttonSelectedColor = colors[++i]; } else { backgroundColor = Color.TRANSPARENT; textColor = Color.TRANSPARENT; buttonBorderColor = Color.TRANSPARENT; buttonBackgroundColor = Color.TRANSPARENT; buttonSelectedColor = Color.TRANSPARENT; } // create dialog with title and a listener to wake up calling thread final AlertDialog dialog = new AlertDialog.Builder(this).create(); dialog.setTitle(args.getString("title")); dialog.setCancelable(false); dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface unused) { synchronized (messageboxSelection) { messageboxSelection.notify(); } } }); // create text TextView message = new TextView(this); message.setGravity(Gravity.CENTER); message.setText(args.getString("message")); if (textColor != Color.TRANSPARENT) { message.setTextColor(textColor); } // create buttons int[] buttonFlags = args.getIntArray("buttonFlags"); int[] buttonIds = args.getIntArray("buttonIds"); String[] buttonTexts = args.getStringArray("buttonTexts"); final SparseArray