Compare commits

...

178 Commits

Author SHA1 Message Date
1998a3d38e cmake: Add option to enable scripting 2023-08-06 00:32:29 +03:00
f166cbc35b cmake: Pull httplib out of ENABLE_WEB_SERVICE
* Services are not considered part of the web service
2023-08-05 15:50:53 +03:00
ebac2e4978 custom_tex_manager: Allow old hash in more cases (#6843) 2023-08-03 00:51:10 +03:00
5b9f4d4129 SOC: Fix setting TTL to default value when TTL = 0 (#6835) 2023-08-02 13:06:51 -07:00
b1b6f08926 citra_qt: fix two graphics configuration bugs (#6840) 2023-08-02 21:38:57 +02:00
7e6a761f07 cmake: fix USE_SYSTEM_BOOST behavior ... (#6837) 2023-08-02 12:20:35 -07:00
6f7612f73d Res cache fixes (#6838)
* rasterizer_cache: Dont consider res_scale during recycle

* rasterizer_cache: Switch to plain erase loop

* rasterizer_cache: Fix crash due to memory corruption
2023-08-02 21:38:45 +03:00
88ea66053e Miscallenious fixes to gl backend and qt frontend (#6834)
* renderer_gl: Make rasterizer normal class member

* It doesn't need to be heap allocated anymore

* gl_rasterizer: Remove default_texture

* It's unused

* gl_rasterizer: General cleanup

* gl_rasterizer: Lower case lambdas

* Match style with review comments from vulkan backend

* rasterizer_cache: Prevent memory leak

* Since the switch from shared_ptr these surfaces were no longer being destroyed properly. Use our garbage collector for that purpose to destroy it safely for both backends

* rasterizer_cache: Make temp copy of old surface

* The custom surface would override the memory region of the old region resulting in garbage data, this ensures the custom surface is constructed correctly

* citra_qt: Manually create dialog tabs

* Allows for custom constructors which is very useful. While at it, global state is now eliminated from configuration

* citra_qt: Eliminate global system usage

* core: Remove global system usage in memory and HIO

* citra_qt: Use qOverload

* tests: Run clang format

* gl_texture_runtime: Fix surface scaling
2023-08-02 01:40:39 +03:00
970f2284d8 http/soc: Various implementations and fixes (#6828) 2023-08-02 00:37:56 +02:00
baf3ea4beb custom_tex_manager: Allow old hash in the dumper (#6832) 2023-08-01 20:38:51 +03:00
35e208b447 Move MiiData to its own namespace and add ChecksummedMiiData (#6824)
* Move mii to own namespace and add checksummed mii data

* Fix compile issues

* Make mii classes trivial and add cast operator

* Fix Android side

* Add new line at the end of files.

* Make miidata a struct and crc16 a u32_be as per switch code.

* Apply suggestions

* Change back crc to u16 and set padding to 0.
2023-07-31 20:38:47 -07:00
f8b8b6e53c core: De-globalize movie (#6659) 2023-08-01 02:57:38 +02:00
a955f02771 rasterizer_cache: Remove runtime allocation caching (#6705)
* rasterizer_cache: Sentence surfaces

* gl_texture_runtime: Remove runtime side allocation cache

* rasterizer_cache: Adjust surface scale during reinterpreration

* Fixes pixelated outlines. Also allows to remove the d24s8 specific hack and is more generic in general

* rasterizer_cache: Remove Expand flag

* Begone!

* rasterizer_cache: Cache framebuffers with surface id

* rasterizer_cache: Sentence texture cubes

* renderer_opengl: Move texture mailbox to separate file

* Makes renderer_opengl cleaner overall and allows to report removal threshold from runtime instead of hardcoding. Vulkan requires this

* rasterizer_cache: Dont flush cache on layout change

* rasterizer_cache: Overhaul framebuffer management

* video_core: Remove duplicate

* rasterizer_cache: Sentence custom surfaces

* Vulkan cannot destroy images immediately so this ensures we use our garbage collector for that purpose
2023-08-01 03:35:41 +03:00
3fedc68230 common: Only use libbacktrace if present. (#6827) 2023-07-31 14:24:27 -07:00
335fb78c5c service/am: Clean up and optimize CIA installation. (#6718) 2023-07-30 21:40:35 +02:00
22c4eb86d7 core/frd: Correct FunctionInfo and stub more functions (#6209) 2023-07-30 04:18:52 +02:00
964f9ee3cf service/gsp: Implement saving of framebuffers in SaveVramSysArea. (#6821)
* service/gsp: Implement saving of framebuffers in SaveVramSysArea.

* Address review comments.

* service/apt: Separate capture info and capture buffer info.

The former is used with the RequestForSysApplet message and GetCaptureInfo.
The latter is used with SendCaptureBufferInfo and ReceiveCaptureBufferInfo.
2023-07-29 00:26:24 -07:00
bb364d9bc0 service/apt: Add and implement more service commands. (#6721)
* service/apt: Add and implement more service commands.

* service/apt: Implement power button.

* Address review comments and fix GetApplicationRunningMode bug.
2023-07-29 00:26:16 -07:00
51996c54f0 audio_core\hle\adts_reader.cpp: Use BitField to parse ADTS header (#6719) 2023-07-28 12:15:58 -07:00
539a1a0b6e service/cfg: Separate out config block defaults and create when not found. (#6716) 2023-07-26 10:33:00 -07:00
8b21b902f2 hw/y2r: Templatize input/output formats. (#6717) 2023-07-25 05:51:57 -07:00
19107cec4b citra-qt: update the separate window titles to use full_name and show Primary/Secondary identifier (#6712)
* citra-qt: update the separate window titles to use full_name and Primary/Secondary window identifier

* build_fullname: remove trailing space
2023-07-25 05:51:46 -07:00
a537f56766 services/cfg: Clean up definitions and access flag handling. (#6711) 2023-07-21 18:04:15 -07:00
b5e1a27a7e rasterizer_cache: Handle texture cubes with duplicate faces (#6710) 2023-07-21 01:55:19 +03:00
a9e390b1b1 frontend: Fix clicking primary screen window touching screen. (#6707) 2023-07-20 15:48:50 -07:00
71582a72a4 sdl: Check correct windowID based on event type. (#6703) 2023-07-19 01:29:13 -07:00
e783b0d4a9 rasterizer_cache: Fixes to (unaligned) texture downloads (#6697)
* rasterizer_cache: Header cleanup

* gl_texture_runtime: Fix incorrect stride in single scanline downloads

* texture_codec: Fix unaligned texture downloads
2023-07-18 17:31:31 +03:00
700c00f021 audio_core/hle: Stub binary requests SaveState and LoadState. (#6684)
* audio_core/hle: Stub binary requests SaveState and LoadState.

* audio_core/hle: Fire DSP binary pipe interrupt on request completion instead of tick.
2023-07-16 17:54:40 -07:00
9cb14044ec kernel: Improvements to process cleanup. (#6680)
* kernel: Properly clean up process threads on exit.

* kernel: Track process-owned memory and free on destruction.

* apt: Implement DoApplicationJump via home menu when available.

* kernel: Move TLS allocation management to owning process.
2023-07-16 17:54:29 -07:00
8b6b58a364 y2r: Pass ConversionConfiguration by copying. (#6690) 2023-07-15 01:57:06 -07:00
e043caac27 hle: Eliminate need to specify command headers for IPC. (#6678) 2023-07-14 17:32:59 -07:00
0bedb28bdc rpc: Fix class hierarchy. (#6694) 2023-07-13 16:29:54 -07:00
c10ffda91f android: Restore notification permission request (#6693)
When we targeted API <32, the notification permission would automatically be requested on startup. This restores that behavior temporarily while we work on new UX.
2023-07-12 18:54:21 -07:00
5e8ae4fa8a qt: Fix per-game config loading for 3DSX/ELF. (#6691)
Co-authored-by: Michael Theall <pigman46@gmail.com>
2023-07-12 18:54:11 -07:00
7a7f485640 core: Cleanup RPC (#6674) 2023-07-12 18:54:02 -07:00
bbf833bceb citra_qt\game_list: Make columns hideable (#6467) 2023-07-12 23:17:16 +02:00
8eebb83c2c service: nfc: Keep tag alive while it's being used (#6687) 2023-07-12 14:01:08 -07:00
d702915624 Remove some global usages of system (#6688) 2023-07-11 21:43:28 -07:00
943d5eeddf citra_qt: Remove image allocation limit (#6682) 2023-07-11 21:43:19 -07:00
f3ac6f054f audio_core: Clean up cubeb backend. (#6677) 2023-07-11 21:43:07 -07:00
a94af8ea62 shader_jit: Add optimizations up to x86-64-v4 (#6668) 2023-07-11 09:21:37 -07:00
6da4853360 kernel: fix typo in recorder.cpp (#6686) 2023-07-11 02:56:36 +02:00
b738584832 android: Update layout indexes (#6673) 2023-07-10 03:05:18 +03:00
1cb34ea0d3 core/memory.*:constify GetPhysicalPointer;
audio_core\hle\source.h: constify `memory_system`
2023-07-09 16:37:28 +05:30
662bb9ba77 hle: Stub some service calls used by the home menu. (#6675) 2023-07-07 22:05:38 -07:00
26e3f96983 service: nfc: Start adapter communication on scan (#6671) 2023-07-07 19:02:39 -07:00
cd3244f139 mic_u: Fix up logic for populating shared memory sample buffer. (#6669) 2023-07-07 19:02:31 -07:00
e5310b25d4 ci-merge: remove use of deprecated pushedDate (#6676) 2023-07-07 22:30:15 +02:00
80033b84cb renderer_software: Fix screen rendering (#6664) 2023-07-06 17:15:59 -07:00
cf9bb90ae3 code: Use std::span where appropriate (#6658)
* code: Use std::span when possible

* code: Prefix memcpy and memcmp with std::
2023-07-07 01:52:40 +03:00
4ccd9f24fb Merge pull request #6638 from GPUCode/new-log
common: Backport yuzu log improvements
2023-07-06 23:44:54 +03:00
753b36c6ef act: Use correct service session limit. (#6670) 2023-07-06 13:16:46 -07:00
c00768d6d0 nfc: Use existing secrets infrastructure for amiibo encryption. (#6652) 2023-07-06 11:45:46 -07:00
4383f6d80a Port yuzu-emu/yuzu#5229: "yuzu/main: Add basic command line arguments" (#5696)
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
2023-07-06 20:44:35 +02:00
dc5ca96c0f service: nfc: Use official names (#6672) 2023-07-06 20:25:05 +02:00
9d4609e29a build: Bundle libraries in-place as well on MSVC. (#6665) 2023-07-06 02:37:06 +02:00
df9cc1b84c ci: Fix CI builds being marked as dirty. (#6656) 2023-07-04 21:02:33 -07:00
13a8969824 build: Clear out remaining compile warnings. (#6662) 2023-07-04 21:00:24 -07:00
d7b4260389 common: Address feedback 2023-07-03 17:13:00 +03:00
2126c240cd core: backport some ResultCode updates (#6645)
Co-authored-by: Lioncash <mathew1800@gmail.com>
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
2023-07-03 02:23:53 +02:00
0b37c1da57 shader_jit/tests: Add additional shader-jit tests (#6648)
* shader_jit/tests: Add support for multiple inputs

Allows for multiple `Vec4f` inputs for each run

* shader_jit/tests: Add additional shader-jit tests

Add some more expansive tests for each of the shader-instructions for
regression-testing.  `MAD`/`MADI` is not added due to an upstream bug in
nihstro:

https://github.com/neobrain/nihstro/issues/68
2023-07-03 02:44:56 +03:00
9527bfffed common: Remove dependency from core 2023-07-03 02:18:37 +03:00
ba98bf058a logging: Address some issues 2023-07-03 02:18:35 +03:00
c88acf7405 Android: Gradle updates (#6653)
* android: Migrate to Kotlin DSL

Includes updates to all android dependencies/ndk (minus billing) and adds support for Kotlin, Android 13, and view binding.

* android: Remove unused tests

* android: Remove unused dependencies
2023-07-02 01:08:27 -07:00
71aea7e571 shader/jit: Use xbyak::util::Cpu for Host capabilities (#6643)
Xbyak has a complete utility-class for determining the host-processor's
ISA-features such as SSE4.1, AVX, AVX2, AVX512{F,VL,DQ,VBMI,etc}, and so
on for further potential optimizations.
2023-07-02 08:05:07 +05:30
3d0a3c2c45 service: nfc: Implement amiibo encryption and appdata (#6340) 2023-06-30 22:15:58 +02:00
9c3e2d0f50 externals: Update boost
* To include stack traces
2023-06-30 12:15:52 +03:00
0ddb095273 logging: Make use of bounded queue 2023-06-30 12:15:52 +03:00
52b9007fcf common: Reduce unused includes 2023-06-30 12:15:52 +03:00
e112421db8 backend: Ensure backend_thread is destructed before message_queue
Ensures that stop_token signals that stop has been requested before destruction of conditional_variable
2023-06-30 12:15:52 +03:00
ae6fda8638 logging: Convert backend_thread into an std::jthread
Was getting an unhandled `invalid_argument` [exception](https://en.cppreference.com/w/cpp/thread/thread/join) during
shutdown on my linux machine. This removes the need for a `StopBackendThread` function entirely since `jthread`
[automatically handles both checking if the thread is joinable and stopping the token before attempting to join](https://en.cppreference.com/w/cpp/thread/jthread/~jthread) in the case that `StartBackendThread` was never called.
2023-06-30 12:15:52 +03:00
197c1adcba Refactor Logging Impl
Loop on stop_token and remove final_entry in Entry.
Move Backend thread out of Impl Constructor to its own function.
Add Start function for backend thread.
Use stop token in PopWait and check if entry filename is nullptr before logging.
2023-06-30 12:15:52 +03:00
fe027a96fb common: Replace lock_guard with scoped_lock 2023-06-30 12:15:52 +03:00
637ade3b25 threadsafe_queue: Fix deadlock
This fixes a lost wakeup in SPSCQueue. If the reader is in just the right position, the writer's notification will be lost and this will be a problem if the writer then does something to wait on the reader.

This was discovered to affect my upcoming stacktrace PR. I don't think any performance decrease will be noticeable because an uncontended mutex is smart enough to skip the syscall. This PR might also resolve some rare deadlocks but I don't know of any examples.
2023-06-30 12:15:52 +03:00
a1443356f1 threadsafe_queue: Add std::stop_token overload to PopWait
Useful for jthreads which make use of the threadsafe queues.
2023-06-30 12:15:52 +03:00
aa39430e2c common/logging: Reduce scope of fmt include 2023-06-30 12:15:52 +03:00
8f51dd9513 common/logging: Move Log::Entry declaration to a separate header
This reduces the load of requiring to include std::chrono in all files which include log.h
2023-06-30 12:15:52 +03:00
98e9f4c32e logging: Fix log filter during initialization
The log filter was being ignored on initialization due to the logging instance being initialized before the config instance, so the log filter was set to its default value.

This fixes that oversight, along with using descriptive exceptions instead of abort() calls.
2023-06-30 12:15:51 +03:00
a8340395a3 logging: Display backtrace on crash
This implements backtraces so we don't have to tell users how to use gdb anymore.

This prints a backtrace after abort or segfault is detected. It also fixes the log getting cut off with the last line containing only a bracket. This change lets us know what caused a crash not just what happened the few seconds before it.

I only know how to add support for Linux with GCC. Also this doesn't work outside of C/C++ such as in dynarmic or certain parts of graphics drivers. The good thing is that it'll try and just crash again but the stack frames are still there so the core dump will work just like before.
2023-06-30 12:15:51 +03:00
3641b9891d logging: Simplify and make thread-safe
This simplifies the logging system.

This also fixes some lost messages on startup.

The simplification is simple. I removed unused functions and moved most things in the .h to the .cpp. I replaced the unnecessary linked list with its contents laid out as three member variables. Anything that went through the linked list now directly accesses the backends. Generic functions are replaced with those for each specific use case and there aren't many. This change increases coupling but we gain back more KISS and encapsulation.

With those changes it was easy to make it thread-safe. I just removed the mutex and turned a boolean atomic. I was planning to use this thread-safety in my next PR about stacktraces. It was actually async-signal-safety at first but I ended up using a different approach. Anyway getting rid of the linked list is important for that because have the list of backends constantly changing complicates things.
2023-06-30 12:15:51 +03:00
8e8ca7d9d0 common: logging: backend: Close the file after exceeding the write limit
There's no point in keeping the file open after the write limit is exceeded. This allows the file to be committed to the disk shortly after it is closed and avoids redundantly checking whether or not the write limit is exceeded.
2023-06-30 12:15:51 +03:00
b57773b1cf common: logging: Restructure backend code 2023-06-30 12:15:51 +03:00
b559c078bc common: logging: backend: Wrap IOFile in a unique_ptr
Allows us to forward declare FileUtil::IOFile.
2023-06-30 12:15:51 +03:00
5c86147ef4 log/backend: Use in-class initializer for FileBackend
We can also avoid redundant constructions of the same string repeatedly.
2023-06-30 12:15:51 +03:00
399f3d4e32 log/backend: Make use of erase_if
Same behavior, but less verbose.
2023-06-30 12:15:51 +03:00
173b84c8ff log/backend: Correct order of const in copy constructor
Follows our predominant coding style. Also explicitly specifies the move
constructor/assignment operator as well.
2023-06-30 12:15:51 +03:00
b4c38372d1 common/log: Move Log namespace into the Common namespace
Forgot to move this over when I moved the rest of the source files with
lacking namespaces over.
2023-06-30 12:15:51 +03:00
4fd0cbebdb logging/backend: Make use of designated initializers
Same behavior, less code.
2023-06-30 12:15:36 +03:00
ca2d87e5e3 renderer_opengl: Add debug scopes to logging (#6650) 2023-06-30 02:16:54 +03:00
d26dcc8e31 ci: Run clang-format and transifex in linux-fresh image. (#6649)
* ci: Run clang-format and transifex in linux-fresh image.

* build: Only add bundle targets for enabled outputs.
2023-06-29 00:44:13 -07:00
0d516f6da5 frontend: Added Hybrid Screen screen layout option (#4542) (#6600)
Signed-off-by: elim <e_sliwka@tuta.io>
2023-06-29 01:42:57 +03:00
2d6aca4563 build: Rework CI and move all bundling into new build target. (#6556)
* build: Rework CI and move all bundling into new build target.

* ci: Use "mingw" in msys2 release names for compatibility.

* ci: Use "osx" in macOS release names for compatibility.

* ci: Disable macOS upload.

Will be moved to a separate PR for canary merge.
2023-06-26 17:42:00 -07:00
2e479fcec5 renderer_vulkan: Add shader generators (#6630) 2023-06-26 16:22:51 +02:00
7edc86a9bc code: Remove outdated comment style (#6640) 2023-06-25 15:22:41 +05:30
9b82de6b24 Refactor software renderer (#6621) 2023-06-24 00:59:18 +02:00
7198243319 android: Update UI strings to reflect desktop counterpart (#6608)
* android: Update UI strings to reflect desktop counterpart

Quick edit to the UI strings to bring the text up to parity with Citra desktop, plus some small QoL changes.

* Update strings.xml
2023-06-23 23:45:49 +01:00
6b8a06e7b4 gl_rasterizer: Reset normal map flag each draw (#6636)
* Fixes normal maps leaking draws
2023-06-24 00:30:16 +03:00
eb118b2a4c Merge pull request #6613 from t895/buncha-adjustments
citra_android: String adjustments
2023-06-23 15:35:54 +01:00
7616496456 video_core: Add debug scopes (#6634) 2023-06-23 03:37:13 +02:00
89663e0db8 build: Fix generating build info using unified source archive. (#6628) 2023-06-20 09:44:20 -07:00
d8db0af1b2 Port yuzu-emu/yuzu#10575: "issue_template: Add link to website, Getting Log Files" (#6629)
Co-authored-by: bm01 <1279721+bm01@users.noreply.github.com>
2023-06-20 15:24:04 +02:00
08970e7ba0 update graphics api button indicator (#6625)
* update graphics api button indicator

This tiny pull request
* update the graphics button indicator when launching or closing a game (graphics button doesn't update with per game configuration)

* Disable graphics button indicator click while in game

* fix crash

* It fixed crash when opening configure dialog in game if the graphics api for the game is different of the global graphics api
2023-06-20 15:27:36 +03:00
d735f5c458 renderer_vulkan: Add vulkan initialization code (#6620)
* common: Move dynamic library to common

* This is so that video_core can use it

* logging: Add vulkan log target

* common: Allow defered library loading

* Also add some comments to the functions

* renderer_vulkan: Add vulkan initialization code

* renderer_vulkan: Address feedback
2023-06-20 15:24:24 +03:00
70225e92f7 externals: Move library headers CMake logic to Citra. (#6627) 2023-06-19 17:08:11 -07:00
bfb6a5b5de common: Add C++ version of Apple authorization logic. (#6616) 2023-06-19 15:50:26 -07:00
03dbdfc12f video_core: Reduce nihstro includes in headers. (#6626) 2023-06-19 15:49:22 -07:00
3faddd5e03 video_core: Add vulkan shaders (#6619) 2023-06-19 17:02:18 +03:00
7c11b9b689 Remove AppImage Themeing (#6618) 2023-06-18 10:24:11 -07:00
35d1b67fd4 Merge pull request #6602 from SachinVin/wall
Chore: enable `-Werror` on GCC and clang
2023-06-18 22:37:39 +05:30
4c8a98a321 common\string_util.cpp: switch to boost::locale::conv for UTF16ToUTF8() and UTF8ToUTF16() (#6623) 2023-06-18 20:00:00 +03:00
982c60c67c common\dynamic_library\ffmpeg.{cpp, h}: fix version check for av_opt_child_class_iterate 2023-06-17 21:24:20 +05:30
7e134421d5 common, input_common, network: fix warnings 2023-06-17 21:24:20 +05:30
946a32d793 android + common: fix warnings 2023-06-17 21:24:20 +05:30
8eb89c260d core: fix warnings 2023-06-17 21:23:58 +05:30
796e8a9f24 video_core:fix warnings 2023-06-17 21:23:58 +05:30
c66594caf8 Enable warnings as errors
cpp-jwt: supress OpenSSL deprecation warnings
2023-06-17 21:23:58 +05:30
06db4ffb17 Merge pull request #6508 from SachinVin/not-the-cia
Android: Offload CIA installation to background thread
2023-06-17 20:44:20 +05:30
7f1ffa2a04 hle: Reduce Y2R stub warnings to debug logs. (#6617) 2023-06-17 01:03:37 -07:00
38435e9b3e Dynamically load FFmpeg and libfdk-aac if available. (#6570) 2023-06-17 02:06:18 +03:00
d807cdfe62 Qt: Fix intermittent crash on exit (#6612)
* Fix null pointer deref on exit

* Fix from review
2023-06-16 22:28:00 +05:30
318d55252f CiaInstallWorker.java: cleanup magic numbers 2023-06-16 22:23:34 +05:30
4d666b88b7 citra_android: Add headers for clock and plugin loader 2023-06-15 03:35:30 -04:00
819d2a33c7 citra_android: Make strings more consistent 2023-06-15 03:35:10 -04:00
c074460f60 android: Bump to gradle 8.0 2023-06-12 18:39:42 +05:30
f5bb17c82e Android: Offload CIA installation to background thread 2023-06-12 18:39:40 +05:30
ccb2a7cbea android: minor refactor disk shadercache 2023-06-10 21:05:14 +05:30
238a574645 qt: Add support for building for iOS. (#6594) 2023-06-07 20:40:53 -07:00
d9bf4fd8a2 externals: Update dynarmic to 6.4.8 (#6596) 2023-06-07 20:25:28 -07:00
54c499ed5b Prepare for Vulkan backend (#6595)
* externals: Add libraries required for vulkan

* build: Add support for downloading bundled MoltenVK.

* ci: Install tools needed for Vulkan.

* citra_qt: Add API status indicator

---------

Co-authored-by: GPUCode <geoster3d@gmail.com>
2023-06-05 07:29:05 -07:00
5b7cc76ba3 Add warning popup when loading save states for the first time (#6565)
* citra_qt: Remove global state usage in GMainWindow

* citra_qt: Add warning when loadings saves for the first time

* citra_qt: Focus window when launching game from cmdline

* citra_qt: Cleanup nullptr checks

* citra_qt: Move setting to UISettings

* renderer_opengl: Remove header
2023-06-05 10:06:00 +03:00
52f88f8fb4 chore: Fix GCC 13 compilation and SoundTouch libraries being installed. (#6593) 2023-06-02 23:11:17 -07:00
abd949fea1 qt: Add NCCH secure 1/2 to keys needed for system titles download. (#6586) 2023-06-02 19:16:48 -07:00
f1ece7c56f audio_core: Fix FDK and FFmpeg compile errors. (#6591) 2023-06-02 19:00:09 -07:00
c67c648c1a mmpx: Fix GLES crashes. (#6588) 2023-06-01 20:52:57 +05:30
723b662604 core: Update minimal system title set. (#6573) 2023-05-31 17:34:31 -07:00
0f5ff64ae6 build: Fix Qt download commands working directory. (#6579) 2023-05-31 15:42:13 -07:00
e33a8a9b26 input_common: sdl: Port yuzu sdl fixes (#6577) 2023-05-31 13:01:46 +03:00
b91fbf3f8e ci: Fix macOS bundle validity issues. (#6572)
* ci: Fix improper copying of macOS artifacts.

* ci: Resign universal macOS app after combining.
2023-05-31 13:01:12 +03:00
4ddb2116bf qt: Allow toggling whether to enter system setup on home menu boot. (#6574) 2023-05-31 11:56:35 +03:00
691e09473e video_core: Add MMPX texture filter (#6564)
* video_core: Add MMPX texture shader

* mmpx: Apply mix to mask alpha edge artifacting

* mmpx: Do not use deprecated texture fuction.
2023-05-31 11:55:46 +03:00
b45c7188c7 chore: Fix some compiler warnings. (#6578) 2023-05-30 12:36:12 -07:00
a1d265325a Merge pull request #6561 from SachinVin/audio
audio_core/hle: Refactor Binary Pipe data structures
2023-05-30 19:02:37 +05:30
1ede2f5b5a audio_core\hle\decoder.h: Minor correction in docs 2023-05-29 08:16:05 +05:30
b452b61e58 audio_core/hle/{fdk, ffmpeg}_decoder:fix typos. (#4) 2023-05-26 07:28:17 +05:30
848116b5be audio_core: Dispose of current audio sink before opening new one. (#6567) 2023-05-26 00:44:56 +02:00
5311c939a2 tests/audio_core: add sanity test cases for LLE vs HLE 2023-05-25 20:23:21 +05:30
8cada619b3 audio_core/hle: Refactor Binary Pipe data structures
audio_core\hle\ffmpeg_decoder.cpp: renames
2023-05-25 20:23:19 +05:30
72b82ef6ed Enable web services on Android in Github build (#6555)
* Enable web services in android

* Fix web services build on android

* clang-format

* Remove unnecessary line

* Set telemetry to be disabled by default on all platforms
2023-05-23 21:36:14 +05:30
2281bf5b0b Add range check for renderer config (#6560) 2023-05-21 19:01:26 -07:00
5c45c97ff9 Implement/Fix more SOC related functions (#6267)
* Implement SOC_U::GetHostByName and partial SOC_U::GetNetworkOpt

* Implement AC::GetWifiStatus, and get proper network interface.

* Minor fixes

* More minor fixes

* Even more fixes

* Fix Get/Set SockOpt

* Implement SendToOther

* Apply suggestions and fix timer advance

* Fix variable name

* Add more sockopt values and fix send/recv flags.

* Fix dontwait logic

* Add missing header for linux

* Remove TCP_STDURG

* Fix poll and add more 3ds <-> platform conversions

* Finish implementing all platform <-> 3ds conversion.

* Disable UDP connreset and fix poll again.

* Fix compile issues

* Apply suggestions

* Fix compiler issues

* Fix compiler errors (again)

* Fix GetAddrInfo

* Use IPC::MakeHeader instead of raw hardcoded value.
2023-05-21 19:01:08 -07:00
975ee15635 audiocore/{hle, lle}: remove dependence on static core timing 2023-05-20 21:27:22 +05:30
fa8c530e10 Debian 11 fix (#6543) 2023-05-19 11:34:17 -07:00
7d6c14e584 dumper: Fix pixel format for filters when passed in via encoder options. (#6553) 2023-05-19 10:58:05 -07:00
40962c4479 sdl: Enable cpuinfo detection. (#6554) 2023-05-19 15:48:30 +02:00
110063aa56 externals: update cubeb (#6548) 2023-05-19 00:24:43 +02:00
a12058ea37 ci: Only pack and upload AppImage builds. (#6545) 2023-05-16 13:01:21 -07:00
b89f5278ac Revive: dumping/ffmpeg_backend: Various fixes (#6528)
* dumping/ffmpeg_backend: Add FPS filter

So that the recorded video can be at 60FPS (which is supported by most encoders) while still maintaining correct speed.

* dumping/ffmpeg_backend: Add HW context support

Required for some HW acceled encoders. Not tested as my devices don't seem to require this.

* CMake: Copy avfilter dll for MSVC

* CMakeLists: Require FFmpeg 4.0

* ffmpeg: Fix dumper compile error on MSVC.

* ffmpeg: Address review comments.

---------

Co-authored-by: zhupengfei <zhupf321@gmail.com>
2023-05-16 02:28:21 -07:00
0768bd8ce0 audio_core: Fix FDK AAC decoding. (#6530) 2023-05-14 19:50:07 -07:00
dc39eac916 build: Ensure bundled libraries are properly signed on macOS. (#6527) 2023-05-11 12:47:18 -07:00
7677ace5ea CMakeLists: Find tsl-robin-map package (#6517) 2023-05-10 15:42:20 +02:00
71a9981430 externals: Link SDL2 statically. (#6461) 2023-05-10 05:08:25 +02:00
d8e74a9ff4 audio_core: Implement Apple AudioToolbox AAC decoder. (#6510) 2023-05-09 16:35:49 -07:00
3a27603e3d qt: Clear finishing key combinations for hot key entry on Qt 6.5+ (#6509) 2023-05-09 02:30:06 -07:00
b9d644b777 Fix additional reinterpretation nonsense (#6521)
* surface_params: Ensure pixel formats are not the same

* rasterizer_cache: Check copyable interval
2023-05-09 12:01:15 +03:00
f9ab0b3042 rasterizer_cache: Make reinterpretation stricter (#6515) 2023-05-07 23:13:01 +03:00
2035433159 externals: Update dynarmic for hotfix. (#6513) 2023-05-07 10:30:35 -07:00
ee025174fb externals: Update dynarmic to 6.4.7 (#6507) 2023-05-07 09:19:03 -07:00
2e47afd48e android: Open cheats by long pressing game in game list (#6491) 2023-05-07 16:01:34 +02:00
ebac6b17b0 qt/ui: Fix typos and warnings of duplicate variable names. (#6511) 2023-05-07 18:49:57 +05:30
b4db9aebf2 gl_shader_disk_cache.cpp: Flush transferable_file and precompiled_file more often (#6483) 2023-05-07 02:34:40 +03:00
2e655f73b8 Rasterizer cache refactor v2 (#6479)
* rasterizer_cache: Switch to template

* Eliminates all opengl references in the rasterizer cache headers
  thus completing the backend abstraction

* rasterizer_cache: Switch to page table

* Surface storage isn't particularly interval sensitive so we can use a page table to make it faster

* rasterizer_cache: Move sampler management out of rasterizer cache

* rasterizer_cache: Remove shared_ptr usage

* Switches to yuzu's slot vector for improved memory locality.

* rasterizer_cache: Rework reinterpretation lookup

* citra_qt: Per game texture filter

* rasterizer_cache: Log additional settings

* gl_texture_runtime: Resolve shadow map comment

* rasterizer_cache: Don't use float for viewport

* gl_texture_runtime: Fix custom allocation recycling

* rasterizer_cache: Minor cleanups

* Cleanup texture cubes when all the faces have been unregistered from the cache

* custom_tex_manager: Allow multiple hash mappings per texture

* code: Move slot vector to common

* rasterizer_cache: Prevent texture cube crashes

* rasterizer_cache: Improve mipmap validation

* CanSubRect now works properly when validating multi-level surfaces, for example Dark Moon validates a 4 level surface from a 3 level one and it works

* gl_blit_handler: Unbind sampler on reinterpretation
2023-05-07 02:34:28 +03:00
322d7a8287 Textures loading screen (#6478)
* Add a loading screen for the preloading textures

*The PreloadTextures() function is called from the EmuThread to prevent citra to freezing

*Add a the preloading textures loadingscreen in loading_screen.cpp

*Add custom_tex_manager.reset() in core.cpp to release ram memory after exiting a game

* Add custom textures loading in EmuThread

* Remove useless variable

* Revert "Add custom textures loading in EmuThread"

This reverts commit 45ed46fa09159f782c5d20a4330b4eb7cfcdc253.

* Moved include from bootmanager.h to bootmanager.cpp
2023-05-07 02:34:14 +03:00
62792b6b0e android: Turn GameInfo into a class (#6494)
By only loading data from disk when creating an instance of this new
class instead of on every method call, we save a lot of file open
operations, which due to SAF are very expensive. This should noticeably
speed up game list scanning.

No intended change in what metadata is shown.
2023-05-06 14:40:11 +05:30
2b8610fcc4 qt: Update CMake translation targets. (#6506) 2023-05-06 11:09:00 +05:30
2273df4d70 qt: Migrate to Qt6. (#6418) 2023-05-05 03:10:34 -07:00
70335a7f4d Merge pull request #6502 from vitor-k/update-catch-zstd
Update catch and zstd
2023-05-04 21:15:08 +05:30
53da17b925 externals: update catch to v3.3.2 2023-05-04 11:12:59 -03:00
7b4e2b3c9d externals: update zstd to v1.5.5 again 2023-05-04 11:08:05 -03:00
689 changed files with 31928 additions and 16399 deletions

View File

@ -5,7 +5,10 @@ export NDK_CCACHE=$(which ccache)
BUILD_FLAVOR=canary ||
BUILD_FLAVOR=nightly
ccache -s
if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then
export ANDROID_KEYSTORE_FILE="${GITHUB_WORKSPACE}/ks.jks"
base64 --decode <<< "${ANDROID_KEYSTORE_B64}" > "${ANDROID_KEYSTORE_FILE}"
fi
cd src/android
chmod +x ./gradlew
@ -13,3 +16,7 @@ chmod +x ./gradlew
./gradlew bundle${BUILD_FLAVOR}Release
ccache -s
if [ ! -z "${ANDROID_KEYSTORE_B64}" ]; then
rm "${ANDROID_KEYSTORE_FILE}"
fi

View File

@ -1,23 +0,0 @@
#!/bin/bash -ex
. ./.ci/common/pre-upload.sh
REV_NAME="citra-android-${GITDATE}-${GITREV}"
[ "${GITHUB_REPOSITORY}" = "citra-emu/citra-canary" ] &&
BUILD_FLAVOR=canary ||
BUILD_FLAVOR=nightly
cp src/android/app/build/outputs/apk/${BUILD_FLAVOR}/release/app-${BUILD_FLAVOR}-release.apk \
"artifacts/${REV_NAME}.apk"
cp src/android/app/build/outputs/bundle/${BUILD_FLAVOR}Release/app-${BUILD_FLAVOR}-release.aab \
"artifacts/${REV_NAME}.aab"
if [ ! -z "${ANDROID_KEYSTORE_B64}" ]
then
echo "Signing apk..."
base64 --decode <<< "${ANDROID_KEYSTORE_B64}" > ks.jks
apksigner sign --ks ks.jks \
--ks-key-alias "${ANDROID_KEY_ALIAS}" \
--ks-pass env:ANDROID_KEYSTORE_PASS "artifacts/${REV_NAME}.apk"
fi

View File

@ -1,28 +0,0 @@
#!/bin/bash -ex
# Copy documentation
cp license.txt "$REV_NAME"
cp README.md "$REV_NAME"
# Copy cross-platform scripting support
cp -r dist/scripting "$REV_NAME"
tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$REV_NAME"
# Find out what release we are building
if [[ "$GITHUB_REF_NAME" =~ ^canary- ]] || [[ "$GITHUB_REF_NAME" =~ ^nightly- ]]; then
RELEASE_NAME=$(echo $GITHUB_REF_NAME | cut -d- -f1)
if [ "$NAME" = "linux-mingw" ]; then
RELEASE_NAME="${RELEASE_NAME}-mingw"
fi
else
RELEASE_NAME=head
fi
mv "$REV_NAME" $RELEASE_NAME
7z a "$REV_NAME.7z" $RELEASE_NAME
# move the compiled archive into the artifacts directory to be uploaded by travis releases
mv "$ARCHIVE_NAME" artifacts/
mv "$REV_NAME.7z" artifacts/

View File

@ -1,6 +0,0 @@
#!/bin/bash -ex
GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
GITREV="`git show -s --format='%h'`"
mkdir -p artifacts

View File

@ -1,3 +0,0 @@
#!/bin/bash -ex
mkdir -p "$HOME/.ccache"
docker run -v $(pwd):/citra -v "$HOME/.ccache":/root/.ccache citraemu/build-environments:linux-appimage /bin/bash -ex /citra/.ci/linux/docker.sh

View File

@ -1,28 +0,0 @@
#!/bin/bash
#Building Citra
mkdir build
cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_FFMPEG_VIDEO_DUMPER=ON
ninja
ctest -VV -C Release
#Building AppDir
DESTDIR="./AppDir" ninja install
mv ./AppDir/usr/local/bin ./AppDir/usr
mv ./AppDir/usr/local/share ./AppDir/usr
rm -rf ./AppDir/usr/local
#Circumvent missing LibFuse in Docker, by extracting the AppImage
export APPIMAGE_EXTRACT_AND_RUN=1
#Copy External Libraries
mkdir -p ./AppDir/usr/plugins/platformthemes
mkdir -p ./AppDir/usr/plugins/styles
cp /usr/lib/x86_64-linux-gnu/qt5/plugins/platformthemes/libqt5ct.so ./AppDir/usr/plugins/platformthemes
cp /usr/lib/x86_64-linux-gnu/qt5/plugins/platformthemes/libqgtk3.so ./AppDir/usr/plugins/platformthemes
cp /usr/lib/x86_64-linux-gnu/qt5/plugins/styles/libqt5ct-style.so ./AppDir/usr/plugins/styles
#Build AppImage
/linuxdeploy-x86_64.AppImage --appdir AppDir --plugin qt --output appimage

View File

@ -1,5 +0,0 @@
#!/bin/bash -ex
. .ci/common/pre-upload.sh
REV_NAME="citra-linux-${GITDATE}-${GITREV}"
mv build/Citra*.AppImage "${GITHUB_WORKSPACE}"/artifacts/${REV_NAME}.AppImage

View File

@ -1,3 +0,0 @@
#!/bin/bash -ex
mkdir -p "$HOME/.ccache"
docker run -v $(pwd):/citra -v "$HOME/.ccache":/root/.ccache citraemu/build-environments:linux-clang-format /bin/bash -ex /citra/.ci/clang-format/docker.sh

View File

@ -1,4 +0,0 @@
#!/bin/bash -ex
# Run clang-format
./.ci/linux-clang-format/script.sh

View File

@ -1,3 +0,0 @@
#!/bin/bash -ex
mkdir -p "$HOME/.ccache"
docker run -v $(pwd):/citra -v "$HOME/.ccache":/root/.ccache citraemu/build-environments:linux-fresh /bin/bash -ex /citra/.ci/linux/docker.sh

View File

@ -1,7 +0,0 @@
#!/bin/bash -ex
mkdir build && cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_FFMPEG_VIDEO_DUMPER=ON
ninja
ctest -VV -C Release

View File

@ -1,19 +0,0 @@
#!/bin/bash -ex
. .ci/common/pre-upload.sh
REV_NAME="citra-linux-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.xz"
COMPRESSION_FLAGS="-cJvf"
mkdir "$REV_NAME"
cp build/bin/Release/citra "$REV_NAME"
cp build/bin/Release/citra-room "$REV_NAME"
cp build/bin/Release/citra-qt "$REV_NAME"
# We need icons on Linux for .desktop entries
mkdir "$REV_NAME/dist"
cp dist/icon.png "$REV_NAME/dist/citra.png"
. .ci/common/post-upload.sh

View File

@ -1,3 +0,0 @@
#!/bin/bash -ex
mkdir -p "$HOME/.ccache"
docker run -v $(pwd):/citra -v "$HOME/.ccache":/root/.ccache citraemu/build-environments:linux-frozen /bin/bash -ex /citra/.ci/linux-frozen/docker.sh

View File

@ -1,15 +0,0 @@
#!/bin/bash -ex
mkdir -p ~/bin/gold
echo '#!/bin/bash' > ~/bin/gold/ld
echo 'gold "$@"' >> ~/bin/gold/ld
chmod a+x ~/bin/gold/ld
export CFLAGS="-B$HOME/bin/gold $CFLAGS"
export CXXFLAGS="-B$HOME/bin/gold $CXXFLAGS"
mkdir build && cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++
ninja
ctest -VV -C Release

View File

@ -1,52 +0,0 @@
#!/usr/bin/python
import sys
import re
import subprocess
from launchpadlib.launchpad import Launchpad
if sys.version_info[0] > 2:
xrange = range
cachedir = '/.launchpadlib/cache/'
launchpad = Launchpad.login_anonymously(
'grab build info', 'production', cachedir, version='devel')
processed_packages = []
deb_file_list = []
def get_url(pkg, distro):
build_ref = launchpad.archives.getByReference(reference='ubuntu').getPublishedBinaries(
binary_name=pkg[0], distro_arch_series='https://api.launchpad.net/devel/ubuntu/' + distro + '/amd64', version=pkg[1], exact_match=True, order_by_date=True).entries[0]
build_link = build_ref['build_link']
deb_name = '{}_{}_{}.deb'.format(pkg[0], pkg[1], 'amd64' if build_ref['architecture_specific'] else 'all')
deb_link = build_link + '/+files/' + deb_name
return [deb_link, deb_name]
def list_dependencies(deb_file):
t = subprocess.check_output(
['bash', '-c', '(dpkg -I {} | grep -oP "^ Depends\: \K.*$") || true'.format(deb_file)])
deps = [i.strip() for i in t.split(',')]
equals_re = re.compile(r'^(.*) \(= (.*)\)$')
return [equals_re.sub(r'\1=\2', i).split('=') for i in filter(equals_re.match, deps)]
def get_package(pkg, distro):
if pkg in processed_packages:
return
print('Getting {}...'.format(pkg[0]))
url = get_url(pkg, distro)
subprocess.check_call(['wget', '--quiet', url[0], '-O', url[1]])
for dep in list_dependencies(url[1]):
get_package(dep, distro)
processed_packages.append(pkg)
deb_file_list.append('./' + url[1])
for i in xrange(1, len(sys.argv), 3):
get_package([sys.argv[i], sys.argv[i + 1]], sys.argv[i + 2])
subprocess.check_call(
['apt-get', 'install', '-y', '--force-yes'] + deb_file_list)

View File

@ -1,3 +0,0 @@
#!/bin/bash -ex
mkdir "$HOME/.ccache" || true
docker run -v $(pwd):/citra -v "$HOME/.ccache":/root/.ccache citraemu/build-environments:linux-mingw /bin/bash -ex /citra/.ci/linux-mingw/docker.sh

View File

@ -1,31 +0,0 @@
#!/bin/bash -ex
# override CI ccache size
mkdir -p "$HOME/.ccache/"
echo 'max_size = 3.0G' > "$HOME/.ccache/ccache.conf"
mkdir build && cd build
cmake .. -G Ninja -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DCITRA_USE_CCACHE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_QT_TRANSLATION=ON -DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_MF=ON -DENABLE_FFMPEG_VIDEO_DUMPER=ON -DCMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE -DCOMPILE_WITH_DWARF=OFF
ninja
echo "Tests skipped"
#ctest -VV -C Release
ccache -s
echo 'Prepare binaries...'
cd ..
mkdir package
QT_PLATFORM_DLL_PATH='/usr/x86_64-w64-mingw32/lib/qt/plugins/platforms/'
find build/ -name "citra*.exe" -exec cp {} 'package' \;
# copy Qt plugins
mkdir package/platforms
cp "${QT_PLATFORM_DLL_PATH}/qwindows.dll" package/platforms/
cp -rv "${QT_PLATFORM_DLL_PATH}/../mediaservice/" package/
cp -rv "${QT_PLATFORM_DLL_PATH}/../imageformats/" package/
cp -rv "${QT_PLATFORM_DLL_PATH}/../styles/" package/
rm -f package/mediaservice/*d.dll
python3 .ci/linux-mingw/scan_dll.py package/*.exe package/imageformats/*.dll "package/"

View File

@ -1,122 +0,0 @@
try:
import lief
except ImportError:
import pefile
import sys
import re
import os
import queue
import shutil
# constant definitions
KNOWN_SYS_DLLS = ['WINMM.DLL', 'MSVCRT.DLL', 'VERSION.DLL', 'MPR.DLL',
'DWMAPI.DLL', 'UXTHEME.DLL', 'DNSAPI.DLL', 'IPHLPAPI.DLL']
# below is for Ubuntu 18.04 with specified PPA enabled, if you are using
# other distro or different repositories, change the following accordingly
DLL_PATH = [
'/usr/x86_64-w64-mingw32/bin/',
'/usr/x86_64-w64-mingw32/lib/',
'/usr/lib/gcc/x86_64-w64-mingw32/9.3-posix/'
]
missing = []
def parse_imports_lief(filename):
results = []
pe = lief.parse(filename)
for entry in pe.imports:
name = entry.name
if name.upper() not in KNOWN_SYS_DLLS and not re.match(string=name, pattern=r'.*32\.DLL'):
results.append(name)
return results
def parse_imports(file_name):
if globals().get('lief'):
return parse_imports_lief(file_name)
results = []
pe = pefile.PE(file_name, fast_load=True)
pe.parse_data_directories()
for entry in pe.DIRECTORY_ENTRY_IMPORT:
current = entry.dll.decode()
current_u = current.upper() # b/c Windows is often case insensitive
# here we filter out system dlls
# dll w/ names like *32.dll are likely to be system dlls
if current_u.upper() not in KNOWN_SYS_DLLS and not re.match(string=current_u, pattern=r'.*32\.DLL'):
results.append(current)
return results
def parse_imports_recursive(file_name, path_list=[]):
q = queue.Queue() # create a FIFO queue
# file_name can be a string or a list for the convience
if isinstance(file_name, str):
q.put(file_name)
elif isinstance(file_name, list):
for i in file_name:
q.put(i)
full_list = []
while q.qsize():
current = q.get_nowait()
print('> %s' % current)
deps = parse_imports(current)
# if this dll does not have any import, ignore it
if not deps:
continue
for dep in deps:
# the dependency already included in the list, skip
if dep in full_list:
continue
# find the requested dll in the provided paths
full_path = find_dll(dep)
if not full_path:
missing.append(dep)
continue
full_list.append(dep)
q.put(full_path)
path_list.append(full_path)
return full_list
def find_dll(name):
for path in DLL_PATH:
for root, _, files in os.walk(path):
for f in files:
if name.lower() == f.lower():
return os.path.join(root, f)
def deploy(name, dst, dry_run=False):
dlls_path = []
parse_imports_recursive(name, dlls_path)
for dll_entry in dlls_path:
if not dry_run:
shutil.copy(dll_entry, dst)
else:
print('[Dry-Run] Copy %s to %s' % (dll_entry, dst))
print('Deploy completed.')
return dlls_path
def main():
if len(sys.argv) < 3:
print('Usage: %s [files to examine ...] [target deploy directory]')
return 1
to_deploy = sys.argv[1:-1]
tgt_dir = sys.argv[-1]
if not os.path.isdir(tgt_dir):
print('%s is not a directory.' % tgt_dir)
return 1
print('Scanning dependencies...')
deploy(to_deploy, tgt_dir)
if missing:
print('Following DLLs are not found: %s' % ('\n'.join(missing)))
return 0
if __name__ == '__main__':
main()

View File

@ -1,13 +0,0 @@
#!/bin/bash -ex
. .ci/common/pre-upload.sh
REV_NAME="citra-windows-mingw-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.gz"
COMPRESSION_FLAGS="-czvf"
mkdir "$REV_NAME"
# get around the permission issues
cp -r package/* "$REV_NAME"
. .ci/common/post-upload.sh

20
.ci/linux.sh Executable file
View File

@ -0,0 +1,20 @@
#!/bin/sh -ex
mkdir build && cd build
cmake .. -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DENABLE_QT_TRANSLATION=ON \
-DCITRA_ENABLE_COMPATIBILITY_REPORTING=ON \
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
-DUSE_DISCORD_PRESENCE=ON
ninja
if [ "$TARGET" = "appimage" ]; then
ninja bundle
fi
ccache -s
ctest -VV -C Release

View File

@ -1,45 +1,43 @@
#!/bin/bash -ex
. .ci/common/pre-upload.sh
REV_NAME="citra-osx-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.gz"
COMPRESSION_FLAGS="-czvf"
ARTIFACTS_LIST=($ARTIFACTS)
BUNDLE_DIR=build/bundle
mkdir build
# Set up the base artifact to combine into.
BASE_ARTIFACT=${ARTIFACTS_LIST[0]}
BASE_ARTIFACT_ARCH="${BASE_ARTIFACT##*-}"
tar xf $BASE_ARTIFACT/$REV_NAME.tar.gz -C $BASE_ARTIFACT
mv $BASE_ARTIFACT/$REV_NAME $REV_NAME
mv $BASE_ARTIFACT $BUNDLE_DIR
# Executable binary paths that need to be combined.
BIN_PATHS=(citra citra-room citra-qt.app/Contents/MacOS/citra-qt)
# Dylib paths that need to be combined.
IFS=$'\n'
DYLIB_PATHS=($(cd $REV_NAME && find . -name '*.dylib'))
DYLIB_PATHS=($(cd $BUNDLE_DIR && find . -name '*.dylib'))
unset IFS
# Combine all of the executable binaries and dylibs.
for OTHER_ARTIFACT in "${ARTIFACTS_LIST[@]:1}"; do
OTHER_ARTIFACT_ARCH="${OTHER_ARTIFACT##*-}"
tar xf $OTHER_ARTIFACT/$REV_NAME.tar.gz -C $OTHER_ARTIFACT
for BIN_PATH in "${BIN_PATHS[@]}"; do
lipo -create -output $REV_NAME/$BIN_PATH $REV_NAME/$BIN_PATH $OTHER_ARTIFACT/$REV_NAME/$BIN_PATH
lipo -create -output $BUNDLE_DIR/$BIN_PATH $BUNDLE_DIR/$BIN_PATH $OTHER_ARTIFACT/$BIN_PATH
done
for DYLIB_PATH in "${DYLIB_PATHS[@]}"; do
# Only merge if the libraries do not have conflicting arches, otherwise it will fail.
DYLIB_INFO=`file $REV_NAME/$DYLIB_PATH`
OTHER_DYLIB_INFO=`file $OTHER_ARTIFACT/$REV_NAME/$DYLIB_PATH`
DYLIB_INFO=`file $BUNDLE_DIR/$DYLIB_PATH`
OTHER_DYLIB_INFO=`file $OTHER_ARTIFACT/$DYLIB_PATH`
if ! [[ "$DYLIB_INFO" =~ "$OTHER_ARTIFACT_ARCH" ]] && ! [[ "$OTHER_DYLIB_INFO" =~ "$BASE_ARTIFACT_ARCH" ]]; then
lipo -create -output $REV_NAME/$DYLIB_PATH $REV_NAME/$DYLIB_PATH $OTHER_ARTIFACT/$REV_NAME/$DYLIB_PATH
lipo -create -output $BUNDLE_DIR/$DYLIB_PATH $BUNDLE_DIR/$DYLIB_PATH $OTHER_ARTIFACT/$DYLIB_PATH
fi
done
done
. .ci/common/post-upload.sh
# Re-sign executables and bundles after combining.
APP_PATHS=(citra citra-room citra-qt.app)
for APP_PATH in "${APP_PATHS[@]}"; do
codesign --deep -fs - $BUNDLE_DIR/$APP_PATH
done

21
.ci/macos.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash -ex
mkdir build && cd build
cmake .. -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_ARCHITECTURES="$TARGET" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DENABLE_QT_TRANSLATION=ON \
-DCITRA_ENABLE_COMPATIBILITY_REPORTING=ON \
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
-DUSE_DISCORD_PRESENCE=ON
ninja
ninja bundle
ccache -s
CURRENT_ARCH=`arch`
if [ "$TARGET" = "$CURRENT_ARCH" ]; then
ctest -VV -C Release
fi

View File

@ -1,36 +0,0 @@
#!/bin/bash -ex
set -o pipefail
export PATH="/usr/local/opt/ccache/libexec:$PATH"
# ccache configurations
export CCACHE_CPP2=yes
export CCACHE_SLOPPINESS=time_macros
export CC="ccache clang"
export CXX="ccache clang++"
export OBJC="clang"
export ASM="clang"
ccache -s
mkdir build && cd build
# TODO: LibreSSL ASM disabled due to platform detection issues in build.
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_ARCHITECTURES="$TARGET_ARCH" \
-DENABLE_QT_TRANSLATION=ON \
-DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
-DUSE_DISCORD_PRESENCE=ON \
-DENABLE_FFMPEG_AUDIO_DECODER=ON \
-DENABLE_FFMPEG_VIDEO_DUMPER=ON \
-DENABLE_ASM=OFF \
-GNinja
ninja
ccache -s
CURRENT_ARCH=`arch`
if [ "$TARGET_ARCH" = "$CURRENT_ARCH" ]; then
ctest -VV -C Release
fi

View File

@ -1,13 +0,0 @@
#!/bin/sh -ex
brew install ccache ninja || true
export QT_VER=5.15.8
mkdir tmp
cd tmp/
# install Qt
wget https://github.com/citra-emu/ext-macos-bin/raw/main/qt/qt-${QT_VER}.7z
7z x qt-${QT_VER}.7z
sudo cp -rv $(pwd)/qt-${QT_VER}/* /usr/local/

View File

@ -1,16 +0,0 @@
#!/bin/bash -ex
. .ci/common/pre-upload.sh
REV_NAME="citra-osx-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.gz"
COMPRESSION_FLAGS="-czvf"
mkdir "$REV_NAME"
cp build/bin/Release/citra "$REV_NAME"
cp -r build/bin/Release/libs "$REV_NAME"
cp -r build/bin/Release/citra-qt.app "$REV_NAME"
cp build/bin/Release/citra-room "$REV_NAME"
. .ci/common/post-upload.sh

48
.ci/pack.sh Executable file
View File

@ -0,0 +1,48 @@
#!/bin/bash -ex
GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
GITREV="`git show -s --format='%h'`"
REV_NAME="citra-${OS}-${TARGET}-${GITDATE}-${GITREV}"
# Find out what release we are building
if [[ "$GITHUB_REF_NAME" =~ ^canary- ]] || [[ "$GITHUB_REF_NAME" =~ ^nightly- ]]; then
RELEASE_NAME=$(echo $GITHUB_REF_NAME | cut -d- -f1)
# For compatibility with existing installs, use mingw/osx in the archive and target names.
if [ "$TARGET" = "msys2" ]; then
REV_NAME="citra-${OS}-mingw-${GITDATE}-${GITREV}"
RELEASE_NAME="${RELEASE_NAME}-mingw"
elif [ "$OS" = "macos" ]; then
REV_NAME="citra-osx-${TARGET}-${GITDATE}-${GITREV}"
fi
else
RELEASE_NAME=head
fi
mkdir -p artifacts
if [ -z "${UPLOAD_RAW}" ]; then
# Archive and upload the artifacts.
mkdir "$REV_NAME"
mv build/bundle/* "$REV_NAME"
if [ "$OS" = "windows" ]; then
ARCHIVE_NAME="${REV_NAME}.zip"
powershell Compress-Archive "$REV_NAME" "$ARCHIVE_NAME"
else
ARCHIVE_NAME="${REV_NAME}.tar.gz"
tar czvf "$ARCHIVE_NAME" "$REV_NAME"
fi
mv "$REV_NAME" $RELEASE_NAME
7z a "$REV_NAME.7z" $RELEASE_NAME
mv "$ARCHIVE_NAME" artifacts/
mv "$REV_NAME.7z" artifacts/
else
# Directly upload the raw artifacts, renamed with the revision.
for ARTIFACT in build/bundle/*; do
FILENAME=$(basename "$ARTIFACT")
EXTENSION="${FILENAME##*.}"
mv "$ARTIFACT" "artifacts/$REV_NAME.$EXTENSION"
done
fi

View File

@ -1,9 +1,13 @@
#!/bin/bash -ex
. .ci/common/pre-upload.sh
GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
GITREV="`git show -s --format='%h'`"
REV_NAME="citra-unified-source-${GITDATE}-${GITREV}"
COMPAT_LIST='dist/compatibility_list/compatibility_list.json'
mkdir artifacts
pip3 install git-archive-all
wget -q https://api.citra-emu.org/gamedb -O "${COMPAT_LIST}"
git describe --abbrev=0 --always HEAD > GIT-COMMIT

View File

@ -1,6 +1,4 @@
#!/bin/bash -e
set -x
#!/bin/bash -ex
echo -e "\e[1m\e[33mBuild tools information:\e[0m"
cmake --version

View File

@ -1,3 +0,0 @@
#!/bin/bash -e
docker run -e TRANSIFEX_API_TOKEN="${TRANSIFEX_API_TOKEN}" -v "$(pwd)":/citra citraemu/build-environments:linux-transifex /bin/sh -e /citra/.travis/transifex/docker.sh

View File

@ -1,21 +0,0 @@
#!/bin/sh -ex
mkdir build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MSVCCache.cmake" \
-DCITRA_USE_CCACHE=ON \
-DENABLE_QT_TRANSLATION=OFF \
-DCITRA_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
-DUSE_DISCORD_PRESENCE=ON \
-DENABLE_MF=ON \
-DENABLE_FFMPEG_VIDEO_DUMPER=ON \
-DOPENSSL_DLL_DIR="C:\Program Files\OpenSSL\bin"
ninja
# show the caching efficiency
buildcache -s
ctest -VV -C Release || echo "::error ::Test error occurred on Windows MSVC build"

View File

@ -1,10 +0,0 @@
#!/bin/sh -ex
BUILDCACHE_VERSION="0.22.3"
choco install wget ninja
# Install buildcache
wget "https://github.com/mbitsnbites/buildcache/releases/download/v${BUILDCACHE_VERSION}/buildcache-win-mingw.zip"
7z x 'buildcache-win-mingw.zip'
mv ./buildcache/bin/buildcache.exe "/c/ProgramData/chocolatey/bin"
rm -rf ./buildcache/

View File

@ -1,41 +0,0 @@
$GITDATE = $(git show -s --date=short --format='%ad') -replace "-", ""
$GITREV = $(git show -s --format='%h')
# Find out what release we are building
if ( $env:GITHUB_REF_NAME -like "*canary-*" -or $env:GITHUB_REF_NAME -like "*nightly-*" ) {
$RELEASE_NAME = ${env:GITHUB_REF_NAME}.split("-")[0]
$RELEASE_NAME = "${RELEASE_NAME}-msvc"
}
else {
$RELEASE_NAME = "head"
}
$MSVC_BUILD_ZIP = "citra-windows-msvc-$GITDATE-$GITREV.zip" -replace " ", ""
$MSVC_SEVENZIP = "citra-windows-msvc-$GITDATE-$GITREV.7z" -replace " ", ""
$BUILD_DIR = ".\build\bin\Release"
# Create artifact directories
mkdir $RELEASE_NAME
mkdir "artifacts"
echo "Starting to pack ${RELEASE_NAME}"
Copy-Item $BUILD_DIR\* -Destination $RELEASE_NAME -Recurse
Remove-Item $RELEASE_NAME\tests.* -ErrorAction ignore
Remove-Item $RELEASE_NAME\*.pdb -ErrorAction ignore
# Copy documentation
Copy-Item license.txt -Destination $RELEASE_NAME
Copy-Item README.md -Destination $RELEASE_NAME
# Copy cross-platform scripting support
Copy-Item dist\scripting -Destination $RELEASE_NAME -Recurse
# Build the final release artifacts
7z a -tzip $MSVC_BUILD_ZIP $RELEASE_NAME\*
7z a $MSVC_SEVENZIP $RELEASE_NAME
Copy-Item $MSVC_BUILD_ZIP -Destination "artifacts"
Copy-Item $MSVC_SEVENZIP -Destination "artifacts"

17
.ci/windows.sh Normal file
View File

@ -0,0 +1,17 @@
#!/bin/sh -ex
mkdir build && cd build
cmake .. -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DENABLE_QT_TRANSLATION=ON \
-DCITRA_ENABLE_COMPATIBILITY_REPORTING=ON \
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
-DUSE_DISCORD_PRESENCE=ON
ninja
ninja bundle
ccache -s
ctest -VV -C Release || echo "::error ::Test error occurred on Windows build"

View File

@ -43,7 +43,7 @@ body:
id: log
attributes:
label: Log File
description: A log file will help our developers to better diagnose and fix the issue.
description: A log file will help our developers to better diagnose and fix the issue. Instructions can be found [here](https://community.citra-emu.org/t/how-to-upload-the-log-file/296).
validations:
required: true
- type: textarea

View File

@ -11,7 +11,7 @@ async function checkBaseChanges(github, context) {
repository(name:$name, owner:$owner) {
ref(qualifiedName:$ref) {
target {
... on Commit { id pushedDate oid }
... on Commit { id committedDate oid }
}
}
}
@ -22,9 +22,9 @@ async function checkBaseChanges(github, context) {
ref: 'refs/heads/master',
};
const result = await github.graphql(query, variables);
const pushedAt = result.repository.ref.target.pushedDate;
console.log(`Last commit pushed at ${pushedAt}.`);
const delta = new Date() - new Date(pushedAt);
const committedAt = result.repository.ref.target.committedDate;
console.log(`Last commit committed at ${committedAt}.`);
const delta = new Date() - new Date(committedAt);
if (delta <= DETECTION_TIME_FRAME) {
console.info('New changes detected, triggering a new build.');
return true;

View File

@ -11,7 +11,7 @@ jobs:
clang-format:
runs-on: ubuntu-latest
container:
image: citraemu/build-environments:linux-clang-format
image: citraemu/build-environments:linux-fresh
options: -u 1001
steps:
- uses: actions/checkout@v3
@ -20,41 +20,7 @@ jobs:
- name: Build
env:
COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
run: ./.ci/linux-clang-format/docker.sh
build:
runs-on: ubuntu-latest
strategy:
matrix:
image: ["linux-appimage", "linux-fresh", "linux-frozen", "linux-mingw"]
container:
image: citraemu/build-environments:${{ matrix.image }}
options: -u 1001
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Set up cache
uses: actions/cache@v3
with:
path: ~/.ccache
key: ${{ runner.os }}-${{ matrix.image }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-${{ matrix.image }}-
- name: Build
run: ./.ci/${{ matrix.image }}/docker.sh
env:
ENABLE_COMPATIBILITY_REPORTING: "ON"
- name: Pack
run: ./.ci/${{ matrix.image }}/upload.sh
if: ${{ matrix.image != 'linux-frozen' }}
env:
NAME: ${{ matrix.image }}
- name: Upload
uses: actions/upload-artifact@v3
if: ${{ matrix.image != 'linux-frozen' }}
with:
name: ${{ matrix.image }}
path: artifacts/
run: ./.ci/clang-format.sh
source:
if: ${{ !github.head_ref }}
runs-on: ubuntu-latest
@ -63,17 +29,57 @@ jobs:
with:
submodules: recursive
- name: Pack
run: ./.ci/source/build.sh
run: ./.ci/source.sh
- name: Upload
uses: actions/upload-artifact@v3
with:
name: source
path: artifacts/
linux:
runs-on: ubuntu-latest
strategy:
matrix:
target: ["appimage", "fresh"]
container:
image: citraemu/build-environments:linux-${{ matrix.target }}
options: -u 1001
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
OS: linux
TARGET: ${{ matrix.target }}
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Set up cache
uses: actions/cache@v3
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ runner.os }}-${{ matrix.target }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-${{ matrix.target }}-
- name: Build
run: ./.ci/linux.sh
- name: Pack
run: ./.ci/pack.sh
if: ${{ matrix.target == 'appimage' }}
- name: Upload
uses: actions/upload-artifact@v3
if: ${{ matrix.target == 'appimage' }}
with:
name: ${{ env.OS }}-${{ env.TARGET }}
path: artifacts/
macos:
runs-on: macos-latest
strategy:
matrix:
arch: ["x86_64", "arm64"]
target: ["x86_64", "arm64"]
env:
CCACHE_CPP2: yes
CCACHE_SLOPPINESS: time_macros
CCACHE_DIR: ${{ github.workspace }}/.ccache
OS: macos
TARGET: ${{ matrix.target }}
steps:
- uses: actions/checkout@v3
with:
@ -81,59 +87,66 @@ jobs:
- name: Set up cache
uses: actions/cache@v3
with:
path: ~/Library/Caches/ccache
key: ${{ runner.os }}-macos-${{ matrix.arch }}-${{ github.sha }}
path: ${{ env.CCACHE_DIR }}
key: ${{ runner.os }}-${{ matrix.target }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-macos-${{ matrix.arch }}-
- name: Install dependencies
run: ./.ci/macos/deps.sh
${{ runner.os }}-${{ matrix.target }}-
- name: Install tools
run: brew install ccache glslang ninja
- name: Build
run: ./.ci/macos/build.sh
env:
MACOSX_DEPLOYMENT_TARGET: "11"
ENABLE_COMPATIBILITY_REPORTING: "ON"
TARGET_ARCH: ${{ matrix.arch }}
- name: Pack
run: ./.ci/macos/upload.sh
- name: Upload
uses: actions/upload-artifact@v3
run: ./.ci/macos.sh
- name: Prepare outputs for caching
run: mv build/bundle $OS-$TARGET
- name: Cache outputs for universal build
uses: actions/cache/save@v3
with:
name: macos-${{ matrix.arch }}
path: artifacts/
path: ${{ env.OS }}-${{ env.TARGET }}
key: ${{ runner.os }}-${{ matrix.target }}-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
macos-universal:
runs-on: macos-latest
needs: macos
env:
OS: macos
TARGET: universal
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Download x86 build
uses: actions/download-artifact@master
- name: Download x86_64 build from cache
uses: actions/cache/restore@v3
with:
name: macos-x86_64
path: macos-x86_64/
- name: Download ARM64 build
uses: actions/download-artifact@master
path: ${{ env.OS }}-x86_64
key: ${{ runner.os }}-x86_64-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
fail-on-cache-miss: true
- name: Download ARM64 build from cache
uses: actions/cache/restore@v3
with:
name: macos-arm64
path: macos-arm64/
path: ${{ env.OS }}-arm64
key: ${{ runner.os }}-arm64-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
fail-on-cache-miss: true
- name: Create universal app
run: ./.ci/macos/universal.sh
run: ./.ci/macos-universal.sh
env:
ARTIFACTS: macos-x86_64 macos-arm64
ARTIFACTS: ${{ env.OS }}-x86_64 ${{ env.OS }}-arm64
- name: Pack
run: ./.ci/pack.sh
# - name: Upload
# uses: actions/upload-artifact@v3
# with:
# name: macos
# name: ${{ env.OS }}-${{ env.TARGET }}
# path: artifacts/
- name: Delete intermediate artifacts
uses: geekyeggo/delete-artifact@v2
with:
name: |
macos-x86_64
macos-arm64
windows:
runs-on: windows-latest
strategy:
matrix:
target: ["msvc", "msys2"]
defaults:
run:
shell: ${{ (matrix.target == 'msys2' && 'msys2') || 'bash' }} {0}
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
OS: windows
TARGET: ${{ matrix.target }}
steps:
- uses: actions/checkout@v3
with:
@ -141,29 +154,50 @@ jobs:
- name: Set up cache
uses: actions/cache@v3
with:
path: ~/.buildcache
key: ${{ runner.os }}-win-${{ github.sha }}
path: ${{ env.CCACHE_DIR }}
key: ${{ runner.os }}-${{ matrix.target }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-win-
- name: Install dependencies
run: ./.ci/windows-msvc/deps.sh
shell: bash
${{ runner.os }}-${{ matrix.target }}-
- name: Set up MSVC
uses: ilammy/msvc-dev-cmd@v1
if: ${{ matrix.target == 'msvc' }}
- name: Install MSVC extra tools
run: choco install ccache ninja wget
if: ${{ matrix.target == 'msvc' }}
- name: Set up MSYS2
uses: msys2/setup-msys2@v2
if: ${{ matrix.target == 'msys2' }}
with:
msystem: clang64
update: true
install: git make p7zip
pacboy: >-
toolchain:p ccache:p cmake:p ninja:p
qt6-base:p qt6-multimedia:p qt6-multimedia-wmf:p qt6-tools:p qt6-translations:p
- name: Setup Vulkan SDK
uses: humbletim/setup-vulkan-sdk@v1.2.0
with:
vulkan-query-version: latest
vulkan-components: Glslang
vulkan-use-cache: true
- name: Test glslangValidator
run: glslangValidator --version
- name: Disable line ending translation
run: git config --global core.autocrlf input
- name: Build
run: ./.ci/windows-msvc/build.sh
shell: bash
env:
ENABLE_COMPATIBILITY_REPORTING: "ON"
run: ./.ci/windows.sh
- name: Pack
run: ./.ci/windows-msvc/upload.ps1
run: ./.ci/pack.sh
- name: Upload
uses: actions/upload-artifact@v3
with:
name: msvc
name: ${{ env.OS }}-${{ env.TARGET }}
path: artifacts/
android:
runs-on: ubuntu-latest
env:
OS: android
TARGET: universal
steps:
- uses: actions/checkout@v3
with:
@ -186,24 +220,28 @@ jobs:
echo $GIT_TAG_NAME
- name: Deps
run: |
sudo apt-get update
sudo apt-get install ccache apksigner -y
sudo add-apt-repository -y ppa:theofficialgman/gpu-tools
sudo apt-get update -y
sudo apt-get install ccache glslang-dev glslang-tools apksigner -y
- name: Build
run: ./.ci/android/build.sh
- name: Copy and sign artifacts
run: JAVA_HOME=$JAVA_HOME_17_X64 ./.ci/android.sh
env:
ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
run: ./.ci/android/upload.sh
- name: Pack
run: ../../../.ci/pack.sh
working-directory: src/android/app
env:
UPLOAD_RAW: 1
- name: Upload
uses: actions/upload-artifact@v3
with:
name: android
path: artifacts/
name: ${{ env.OS }}-${{ env.TARGET }}
path: src/android/app/artifacts/
transifex:
runs-on: ubuntu-latest
container: citraemu/build-environments:linux-transifex
container: citraemu/build-environments:linux-fresh
if: ${{ github.repository == 'citra-emu/citra' && !github.head_ref }}
steps:
- uses: actions/checkout@v3
@ -211,12 +249,12 @@ jobs:
submodules: recursive
fetch-depth: 0
- name: Update Translation
run: ./.ci/transifex/docker.sh
run: ./.ci/transifex.sh
env:
TX_TOKEN: ${{ secrets.TRANSIFEX_API_TOKEN }}
release:
runs-on: ubuntu-latest
needs: [build, android, macos-universal, source, windows]
needs: [windows, linux, macos-universal, android, source]
if: ${{ startsWith(github.ref, 'refs/tags/') }}
steps:
- uses: actions/download-artifact@v3

4
.gitignore vendored
View File

@ -13,6 +13,8 @@ src/common/scm_rev.cpp
.vs/
.vscode/
.cache/
cmake-build-debug/
cmake-build-release/
CMakeLists.txt.user*
# *nix related
@ -41,4 +43,6 @@ Thumbs.db
repo/
# GitHub Actions generated files
.ccache/
node_modules/
VULKAN_SDK/

23
.gitmodules vendored
View File

@ -36,7 +36,7 @@
url = https://github.com/mozilla/cubeb
[submodule "discord-rpc"]
path = externals/discord-rpc
url = https://github.com/discord/discord-rpc.git
url = https://github.com/yuzu-emu/discord-rpc.git
[submodule "cpp-jwt"]
path = externals/cpp-jwt
url = https://github.com/arun11299/cpp-jwt.git
@ -64,6 +64,21 @@
[submodule "dds-ktx"]
path = externals/dds-ktx
url = https://github.com/septag/dds-ktx
[submodule "externals/openal-soft"]
path = externals/openal-soft
url = https://github.com/kcat/openal-soft
[submodule "openal-soft"]
path = externals/openal-soft
url = https://github.com/kcat/openal-soft
[submodule "glslang"]
path = externals/glslang
url = https://github.com/KhronosGroup/glslang
[submodule "vma"]
path = externals/vma
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
[submodule "vulkan-headers"]
path = externals/vulkan-headers
url = https://github.com/KhronosGroup/Vulkan-Headers
[submodule "sirit"]
path = externals/sirit
url = https://github.com/yuzu-emu/sirit
[submodule "library-headers"]
path = externals/library-headers/library-headers
url = https://github.com/citra-emu/ext-library-headers.git

View File

@ -5,6 +5,10 @@ cmake_minimum_required(VERSION 3.15)
cmake_policy(SET CMP0092 NEW)
# Enforce new LTO setting
cmake_policy(SET CMP0069 NEW)
# Honor visibility properties for all targets
# Set the default so subdirectory cmake_minimum_required calls won't unset the policy.
cmake_policy(SET CMP0063 NEW)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules")
@ -14,66 +18,71 @@ include(CMakeDependentOption)
project(citra LANGUAGES C CXX ASM)
if (APPLE)
enable_language(OBJC)
# Silence warnings on empty objects, for example when platform-specific code is #ifdef'd out.
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
if (IOS)
# Minimum iOS 14
set(CMAKE_OSX_DEPLOYMENT_TARGET "14.0")
# Enable searching CMAKE_PREFIX_PATH for bundled dependencies.
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
else()
# Minimum macOS 11
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0")
endif()
endif()
option(ENABLE_LTO "Enable link time optimization" OFF)
if (CMAKE_BUILD_TYPE STREQUAL Debug)
set(IS_DEBUG_BUILD ON)
else()
set(IS_DEBUG_BUILD OFF)
endif()
option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
option(ENABLE_SDL2 "Enable using SDL2" ON)
CMAKE_DEPENDENT_OPTION(ENABLE_SDL2_FRONTEND "Enable the SDL2 frontend" ON "ENABLE_SDL2;NOT ANDROID AND NOT IOS" OFF)
option(USE_SYSTEM_SDL2 "Use the system SDL2 lib (instead of the bundled one)" OFF)
# Set bundled qt as dependent options.
option(ENABLE_QT "Enable the Qt frontend" ON)
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
CMAKE_DEPENDENT_OPTION(CITRA_USE_BUNDLED_QT "Download bundled Qt binaries" ON "ENABLE_QT;MSVC" OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_QT_UPDATER "Enable built-in updater for the Qt frontend" ON "NOT IOS" OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_TESTS "Enable generating tests executable" ON "NOT IOS" OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_DEDICATED_ROOM "Enable generating dedicated room executable" ON "NOT ANDROID AND NOT IOS" OFF)
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
if (MSVC)
set(OPENSSL_DLL_DIR "" CACHE PATH "Location of the Openssl dlls")
endif()
option(ENABLE_SCRIPTING "Enable RPC server for scripting" ON)
option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
CMAKE_DEPENDENT_OPTION(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT IOS" OFF)
option(ENABLE_OPENAL "Enables the OpenAL audio backend" ON)
CMAKE_DEPENDENT_OPTION(ENABLE_LIBUSB "Enable libusb for GameCube Adapter support" ON "NOT IOS" OFF)
option(ENABLE_FFMPEG_AUDIO_DECODER "Enable FFmpeg audio (AAC) decoder" OFF)
option(ENABLE_FFMPEG_VIDEO_DUMPER "Enable FFmpeg video dumper" OFF)
if (ENABLE_FFMPEG_AUDIO_DECODER OR ENABLE_FFMPEG_VIDEO_DUMPER)
set(ENABLE_FFMPEG ON)
endif()
CMAKE_DEPENDENT_OPTION(CITRA_USE_BUNDLED_FFMPEG "Download bundled FFmpeg binaries" ON "ENABLE_FFMPEG;MSVC OR APPLE" OFF)
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
option(CITRA_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
CMAKE_DEPENDENT_OPTION(ENABLE_MF "Use Media Foundation decoder (preferred over FFmpeg)" ON "WIN32" OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_AUDIOTOOLBOX "Use AudioToolbox decoder (preferred over FFmpeg)" ON "APPLE" OFF)
CMAKE_DEPENDENT_OPTION(COMPILE_WITH_DWARF "Add DWARF debugging information" ON "MINGW" OFF)
option(USE_SYSTEM_BOOST "Use the system Boost libs (instead of the bundled ones)" OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_FDK "Use FDK AAC decoder" OFF "NOT ENABLE_FFMPEG_AUDIO_DECODER;NOT ENABLE_MF" OFF)
CMAKE_DEPENDENT_OPTION(CITRA_BUNDLE_LIBRARIES "Bundle dependent libraries with the output executables" ON "APPLE" OFF)
# Compile options
CMAKE_DEPENDENT_OPTION(COMPILE_WITH_DWARF "Add DWARF debugging information" ${IS_DEBUG_BUILD} "MINGW" OFF)
option(ENABLE_LTO "Enable link time optimization" OFF)
option(CITRA_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
option(CITRA_WARNINGS_AS_ERRORS "Enable warnings as errors" ON)
if (CITRA_USE_PRECOMPILED_HEADERS)
if (MSVC AND CCACHE)
# buildcache does not properly cache PCH files, leading to compilation errors.
# See https://github.com/mbitsnbites/buildcache/discussions/230
message(WARNING "Buildcache does not properly support Precompiled Headers. Disabling PCH")
set(CITRA_USE_PRECOMPILED_HEADERS OFF)
endif()
if(APPLE)
message(WARNING "Precompiled Headers currently do not work on Apple. Disabling PCH")
set(CITRA_USE_PRECOMPILED_HEADERS OFF)
endif()
endif()
# System library options
CMAKE_DEPENDENT_OPTION(USE_SYSTEM_QT "Use the system Qt lib (instead of the bundled one)" OFF "ENABLE_QT;MSVC OR APPLE" ON)
CMAKE_DEPENDENT_OPTION(USE_SYSTEM_MOLTENVK "Use the system MoltenVK lib (instead of the bundled one)" OFF "APPLE" OFF)
option(USE_SYSTEM_SDL2 "Use the system SDL2 lib (instead of the bundled one)" OFF)
option(USE_SYSTEM_BOOST "Use the system Boost libs (instead of the bundled ones)" OFF)
option(USE_SYSTEM_OPENSSL "Use the system OpenSSL libs (instead of the bundled LibreSSL)" OFF)
option(USE_SYSTEM_LIBUSB "Use the system libusb (instead of the bundled libusb)" OFF)
if (CITRA_USE_PRECOMPILED_HEADERS)
message(STATUS "Using Precompiled Headers.")
set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON)
@ -123,7 +132,10 @@ function(check_submodules_present)
endif()
endforeach()
endfunction()
check_submodules_present()
if (EXISTS "${PROJECT_SOURCE_DIR}/.git/objects")
# only check submodules when source is obtained via Git
check_submodules_present()
endif()
configure_file(${PROJECT_SOURCE_DIR}/dist/compatibility_list/compatibility_list.qrc
${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc
@ -186,9 +198,15 @@ message(STATUS "Target architecture: ${ARCHITECTURE}")
# boost asio's concept usage doesn't play nicely with some compilers yet.
add_definitions(-DBOOST_ASIO_DISABLE_CONCEPTS)
# boost can have issues compiling with C++17 and up on newer versions of Clang.
add_definitions(-DBOOST_NO_CXX98_FUNCTION_BASE)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Apply consistent visibility settings.
set(CMAKE_CXX_VISIBILITY_PRESET default)
set(CMAKE_VISIBILITY_INLINES_HIDDEN NO)
# set up output paths for executable binaries
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/$<CONFIG>)
@ -201,89 +219,43 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if (ENABLE_QT)
if (CITRA_USE_BUNDLED_QT)
download_qt_external(5.15.2 QT_PREFIX)
list(APPEND CMAKE_PREFIX_PATH ${QT_PREFIX})
if (NOT USE_SYSTEM_QT)
download_qt(6.5.0)
endif()
find_package(Qt5 REQUIRED COMPONENTS Widgets Multimedia Concurrent)
find_package(Qt6 REQUIRED COMPONENTS Widgets Multimedia Concurrent)
if (UNIX AND NOT APPLE)
find_package(Qt5 REQUIRED COMPONENTS DBus)
find_package(Qt6 REQUIRED COMPONENTS DBus)
endif()
if (ENABLE_QT_TRANSLATION)
find_package(Qt5 REQUIRED COMPONENTS LinguistTools)
endif()
if (NOT CITRA_USE_BUNDLED_QT)
# Make sure the Qt bin directory is in the prefix path for later consumers.
get_target_property(qmake_executable Qt5::qmake IMPORTED_LOCATION)
get_filename_component(qt_bin_dir "${qmake_executable}" DIRECTORY)
list(APPEND CMAKE_PREFIX_PATH ${qt_bin_dir})
find_package(Qt6 REQUIRED COMPONENTS LinguistTools)
endif()
endif()
# Ensure libusb is properly configured (based on dolphin libusb include)
if (ENABLE_LIBUSB)
if(NOT APPLE)
include(FindPkgConfig)
find_package(LibUSB)
endif()
if (NOT LIBUSB_FOUND)
add_subdirectory(externals/libusb)
set(LIBUSB_INCLUDE_DIR "")
set(LIBUSB_LIBRARIES usb)
endif()
endif()
# Use system tsl::robin_map if available (otherwise we fallback to version bundled with dynarmic)
find_package(tsl-robin-map QUIET)
if (ENABLE_FFMPEG)
if (CITRA_USE_BUNDLED_FFMPEG)
if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND "x86_64" IN_LIST ARCHITECTURE)
set(FFmpeg_VER "ffmpeg-4.1-win64")
elseif (APPLE)
set(FFmpeg_VER "ffmpeg-6.0")
else()
message(FATAL_ERROR "No bundled FFmpeg binaries for your toolchain. Disable CITRA_USE_BUNDLED_FFMPEG and provide your own.")
endif()
if (DEFINED FFmpeg_VER)
download_bundled_external("ffmpeg/" ${FFmpeg_VER} FFmpeg_PREFIX)
set(FFMPEG_DIR "${FFmpeg_PREFIX}")
endif()
endif()
if (ENABLE_FFMPEG_VIDEO_DUMPER)
find_package(FFmpeg REQUIRED COMPONENTS avcodec avformat avutil swscale swresample)
else()
find_package(FFmpeg REQUIRED COMPONENTS avcodec)
endif()
if ("${FFmpeg_avcodec_VERSION}" VERSION_LESS "57.48.101")
message(FATAL_ERROR "Found version for libavcodec is too low. The required version is at least 57.48.101 (included in FFmpeg 3.1 and later).")
endif()
endif()
if (ENABLE_FFMPEG_VIDEO_DUMPER)
add_definitions(-DENABLE_FFMPEG_VIDEO_DUMPER)
endif()
if (ENABLE_FDK)
find_library(FDK_AAC fdk-aac DOC "The path to fdk_aac library")
if(FDK_AAC STREQUAL "FDK_AAC-NOTFOUND")
message(FATAL_ERROR "fdk_aac library not found.")
endif()
endif()
# Platform-specific library requirements
# ======================================
if (APPLE)
# Umbrella framework for everything GUI-related
find_library(COCOA_LIBRARY Cocoa)
find_library(AVFOUNDATION_LIBRARY AVFoundation)
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${AVFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
if (NOT USE_SYSTEM_MOLTENVK)
download_moltenvk()
endif()
find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED)
message(STATUS "Using MoltenVK at ${MOLTENVK_LIBRARY}.")
if (NOT IOS)
# Umbrella framework for everything GUI-related
find_library(COCOA_LIBRARY Cocoa REQUIRED)
endif()
find_library(AVFOUNDATION_LIBRARY AVFoundation REQUIRED)
find_library(IOSURFACE_LIBRARY IOSurface REQUIRED)
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${AVFOUNDATION_LIBRARY} ${IOSURFACE_LIBRARY} ${MOLTENVK_LIBRARY})
elseif (WIN32)
# WSAPoll and SHGetKnownFolderPath (AppData/Roaming) didn't exist before WinNT 6.x (Vista)
add_definitions(-D_WIN32_WINNT=0x0601 -DWINVER=0x0601)
set(PLATFORM_LIBRARIES winmm ws2_32)
if (MINGW)
# PSAPI is the Process Status API
@ -333,7 +305,7 @@ if (CLANG_FORMAT)
add_custom_target(clang-format
COMMAND powershell.exe -Command "Get-ChildItem '${SRCS}/*' -Include *.cpp,*.h,*.mm -Recurse | Foreach {&'${CLANG_FORMAT}' -i $_.fullname}"
COMMENT ${CCOMMENT})
endif()
endif()
else()
add_custom_target(clang-format
COMMAND find ${SRCS} -iname *.h -o -iname *.cpp -o -iname *.mm | xargs ${CLANG_FORMAT} -i
@ -370,13 +342,6 @@ function(get_timestamp _var)
set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction()
# Prevent boost from linking against libs when building
add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY
-DBOOST_SYSTEM_NO_LIB
-DBOOST_DATE_TIME_NO_LIB
-DBOOST_REGEX_NO_LIB
)
# generate git/build information
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REF_SPEC GIT_REV)
@ -384,22 +349,23 @@ git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
get_timestamp(BUILD_DATE)
if (NOT USE_SYSTEM_BOOST)
add_definitions( -DBOOST_ALL_NO_LIB )
# Boost
# Prevent boost from linking against libs when building
add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY
-DBOOST_SYSTEM_NO_LIB
-DBOOST_DATE_TIME_NO_LIB
-DBOOST_REGEX_NO_LIB
)
if (USE_SYSTEM_BOOST)
find_package(Boost 1.70.0 COMPONENTS container locale serialization iostreams REQUIRED)
endif()
enable_testing()
add_subdirectory(externals)
# See externals/CMakeLists.txt
foreach(def ${CRYPTOPP_COMPILE_DEFINITIONS})
add_definitions(-D${def})
endforeach()
# Boost
if (USE_SYSTEM_BOOST)
find_package(Boost 1.70.0 COMPONENTS serialization iostreams REQUIRED)
else()
# Boost (bundled)
if (NOT USE_SYSTEM_BOOST)
add_definitions( -DBOOST_ALL_NO_LIB )
add_library(Boost::boost ALIAS boost)
add_library(Boost::serialization ALIAS boost_serialization)
add_library(Boost::iostreams ALIAS boost_iostreams)
@ -414,6 +380,11 @@ if (ENABLE_SDL2 AND USE_SYSTEM_SDL2)
add_library(SDL2::SDL2 ALIAS SDL2)
endif()
if (ENABLE_LIBUSB AND USE_SYSTEM_LIBUSB)
include(FindPkgConfig)
find_package(LibUSB)
endif()
add_subdirectory(src)
add_subdirectory(dist/installer)
@ -425,6 +396,20 @@ else()
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT citra)
endif()
# Create target for outputting distributable bundles.
if (NOT ANDROID AND NOT IOS)
include(BundleTarget)
if (ENABLE_SDL2_FRONTEND)
bundle_target(citra)
endif()
if (ENABLE_QT)
bundle_target(citra-qt)
endif()
if (ENABLE_DEDICATED_ROOM)
bundle_target(citra-room)
endif()
endif()
# Installation instructions
# =========================
@ -433,7 +418,7 @@ endif()
# http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
# http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html
if(ENABLE_QT AND UNIX AND NOT APPLE)
install(FILES "${PROJECT_SOURCE_DIR}/dist/citra.desktop"
install(FILES "${PROJECT_SOURCE_DIR}/dist/citra-qt.desktop"
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/applications")
install(FILES "${PROJECT_SOURCE_DIR}/dist/citra.svg"
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps")

View File

@ -12,7 +12,7 @@ endif()
list(APPEND CMAKE_MODULE_PATH "${BASE_DIR}/CMakeModules")
include(DownloadExternals)
download_qt_external(tools_ifw QT_PREFIX)
download_qt(tools_ifw QT_PREFIX)
file(GLOB_RECURSE INSTALLER_BASE "${QT_PREFIX}/**/installerbase*")
file(GLOB_RECURSE BINARY_CREATOR "${QT_PREFIX}/**/binarycreator*")

View File

@ -1,62 +0,0 @@
# Bundles libraries with an output executable.
# Parameters:
# - TYPE: "qt" or "standalone". The type of app to bundle.
# - "qt" uses windeployqt/macdeployqt to bundle Qt and other libraries.
# - "standalone" copies dependent libraries to a "libs" folder alongside the executable file.
# - EXECUTABLE_PATH: Path to the executable binary.
# TODO: This does not really work fully for Windows yet, some libraries are missing from the output.
# TODO: Leaving a basic framework of Windows support here to be iterated on in the future.
if (WIN32)
message(FATAL_ERROR "Advanced library bundling is not yet supported for Windows.")
endif()
if ("${TYPE}" STREQUAL "qt")
get_filename_component(executable_dir ${EXECUTABLE_PATH} DIRECTORY)
# Bundle dependencies using appropriate Qt tool.
if (WIN32)
find_program(WINDEPLOYQT_EXECUTABLE windeployqt)
execute_process(COMMAND ${WINDEPLOYQT_EXECUTABLE} ${EXECUTABLE_PATH}
--no-compiler-runtime --no-system-d3d-compiler --no-opengl-sw --no-translations
--plugindir "${executable_dir}/plugins")
elseif (APPLE)
get_filename_component(contents_dir ${executable_dir} DIRECTORY)
get_filename_component(bundle_dir ${contents_dir} DIRECTORY)
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt)
execute_process(COMMAND ${MACDEPLOYQT_EXECUTABLE} ${bundle_dir} -executable=${EXECUTABLE_PATH} -always-overwrite)
else()
message(FATAL_ERROR "Unsupported OS for Qt-based library bundling.")
endif()
else()
# Resolve dependent library files.
file(GET_RUNTIME_DEPENDENCIES
EXECUTABLES ${EXECUTABLE_PATH}
RESOLVED_DEPENDENCIES_VAR resolved_deps
UNRESOLVED_DEPENDENCIES_VAR unresolved_deps
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll")
# Determine libraries directory.
get_filename_component(executable_dir ${EXECUTABLE_PATH} DIRECTORY)
if (WIN32)
# Same directory since we don't have rpath.
set(lib_dir ${executable_dir})
else()
set(lib_dir ${executable_dir}/libs)
endif()
# Copy library files to bundled output.
file(MAKE_DIRECTORY ${lib_dir})
foreach (lib_file ${resolved_deps})
# Use native copy to turn symlinks into normal files.
execute_process(COMMAND cp -L ${lib_file} ${lib_dir})
endforeach()
# Add libs directory to executable rpath where applicable.
if (APPLE)
execute_process(COMMAND install_name_tool -add_rpath "@loader_path/libs" ${EXECUTABLE_PATH})
elseif (UNIX)
execute_process(COMMAND patchelf --set-rpath '$ORIGIN/../libs' ${EXECUTABLE_PATH})
endif()
endif()

View File

@ -0,0 +1,271 @@
if (BUNDLE_TARGET_EXECUTE)
# --- Bundling method logic ---
function(bundle_qt executable_path)
if (WIN32)
get_filename_component(executable_parent_dir "${executable_path}" DIRECTORY)
find_program(windeployqt_executable windeployqt6)
# Create a qt.conf file pointing to the app directory.
# This ensures Qt can find its plugins.
file(WRITE "${executable_parent_dir}/qt.conf" "[Paths]\nprefix = .")
message(STATUS "Executing windeployqt for executable ${executable_path}")
execute_process(COMMAND "${windeployqt_executable}" "${executable_path}"
--no-compiler-runtime --no-system-d3d-compiler --no-opengl-sw --no-translations
--plugindir "${executable_parent_dir}/plugins")
# Remove the FFmpeg multimedia plugin as we don't include FFmpeg.
# We want to use the Windows media plugin instead, which is also included.
file(REMOVE "${executable_parent_dir}/plugins/multimedia/ffmpegmediaplugin.dll")
elseif (APPLE)
get_filename_component(executable_name "${executable_path}" NAME_WE)
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt6)
message(STATUS "Executing macdeployqt for executable ${executable_path}")
execute_process(
COMMAND "${MACDEPLOYQT_EXECUTABLE}"
"${executable_path}"
"-executable=${executable_path}/Contents/MacOS/${executable_name}"
-always-overwrite)
# Bundling libraries can rewrite path information and break code signatures of system libraries.
# Perform an ad-hoc re-signing on the whole app bundle to fix this.
execute_process(COMMAND codesign --deep -fs - "${executable_path}")
else()
message(FATAL_ERROR "Unsupported OS for Qt bundling.")
endif()
endfunction()
function(bundle_appimage bundle_dir executable_path source_path binary_path linuxdeploy_executable enable_qt)
get_filename_component(executable_name "${executable_path}" NAME_WE)
set(appdir_path "${binary_path}/AppDir-${executable_name}")
if (enable_qt)
# Find qmake to make sure the plugin uses the right version of Qt.
find_program(QMAKE_EXECUTABLE qmake6)
set(extra_linuxdeploy_env "QMAKE=${QMAKE_EXECUTABLE}")
set(extra_linuxdeploy_args --plugin qt)
endif()
message(STATUS "Creating AppDir for executable ${executable_path}")
execute_process(COMMAND ${CMAKE_COMMAND} -E env
${extra_linuxdeploy_env}
"${linuxdeploy_executable}"
${extra_linuxdeploy_args}
--plugin checkrt
--executable "${executable_path}"
--icon-file "${source_path}/dist/citra.svg"
--desktop-file "${source_path}/dist/${executable_name}.desktop"
--appdir "${appdir_path}")
if (enable_qt)
set(qt_hook_file "${appdir_path}/apprun-hooks/linuxdeploy-plugin-qt-hook.sh")
file(READ "${qt_hook_file}" qt_hook_contents)
# Add Cinnamon to list of DEs for GTK3 theming.
string(REPLACE
"*XFCE*"
"*X-Cinnamon*|*XFCE*"
qt_hook_contents "${qt_hook_contents}")
# Wayland backend crashes due to changed schemas in Gnome 40.
string(REPLACE
"export QT_QPA_PLATFORMTHEME=gtk3"
"export QT_QPA_PLATFORMTHEME=gtk3; export GDK_BACKEND=x11"
qt_hook_contents "${qt_hook_contents}")
file(WRITE "${qt_hook_file}" "${qt_hook_contents}")
endif()
message(STATUS "Creating AppImage for executable ${executable_path}")
execute_process(COMMAND ${CMAKE_COMMAND} -E env
"OUTPUT=${bundle_dir}/${executable_name}.AppImage"
"${linuxdeploy_executable}"
--output appimage
--appdir "${appdir_path}")
endfunction()
function(bundle_standalone executable_path original_executable_path bundle_library_paths)
get_filename_component(executable_parent_dir "${executable_path}" DIRECTORY)
# Resolve dependent library files if they were not passed in.
message(STATUS "Determining runtime dependencies of ${executable_path} using library paths ${bundle_library_paths}")
file(GET_RUNTIME_DEPENDENCIES
EXECUTABLES ${original_executable_path}
RESOLVED_DEPENDENCIES_VAR resolved_deps
UNRESOLVED_DEPENDENCIES_VAR unresolved_deps
DIRECTORIES ${bundle_library_paths}
POST_EXCLUDE_REGEXES ".*system32.*")
if (WIN32)
# Same directory since we don't have rpath.
set(lib_dir "${executable_parent_dir}")
else()
set(lib_dir "${executable_parent_dir}/libs")
endif()
# Copy files to bundled output.
if (resolved_deps)
file(MAKE_DIRECTORY ${lib_dir})
foreach (lib_file IN LISTS resolved_deps)
message(STATUS "Bundling library ${lib_file}")
# Use native copy to turn symlinks into normal files.
execute_process(COMMAND cp -L "${lib_file}" "${lib_dir}")
endforeach()
endif()
# Add libs directory to executable rpath where applicable.
if (APPLE)
execute_process(COMMAND install_name_tool -add_rpath "@loader_path/libs" "${executable_path}")
elseif (UNIX)
execute_process(COMMAND patchelf --set-rpath '$ORIGIN/../libs' "${executable_path}")
endif()
endfunction()
# --- Root bundling logic ---
set(bundle_dir ${BINARY_PATH}/bundle)
# On Linux, always bundle an AppImage.
if (DEFINED LINUXDEPLOY)
if (IN_PLACE)
message(FATAL_ERROR "Cannot bundle for Linux in-place.")
endif()
bundle_appimage("${bundle_dir}" "${EXECUTABLE_PATH}" "${SOURCE_PATH}" "${BINARY_PATH}" "${LINUXDEPLOY}" ${BUNDLE_QT})
else()
if (IN_PLACE)
message(STATUS "Bundling dependencies in-place")
set(bundled_executable_path "${EXECUTABLE_PATH}")
else()
message(STATUS "Copying base executable ${EXECUTABLE_PATH} to output directory ${bundle_dir}")
file(COPY ${EXECUTABLE_PATH} DESTINATION ${bundle_dir})
get_filename_component(bundled_executable_name "${EXECUTABLE_PATH}" NAME)
set(bundled_executable_path "${bundle_dir}/${bundled_executable_name}")
endif()
if (BUNDLE_QT)
bundle_qt("${bundled_executable_path}")
endif()
if (WIN32 OR NOT BUNDLE_QT)
bundle_standalone("${bundled_executable_path}" "${EXECUTABLE_PATH}" "${BUNDLE_LIBRARY_PATHS}")
endif()
endif()
else()
# --- Bundling target creation logic ---
# Downloads and extracts a linuxdeploy component.
function(download_linuxdeploy_component base_dir name executable_name)
set(executable_file "${base_dir}/${executable_name}")
if (NOT EXISTS "${executable_file}")
message(STATUS "Downloading ${executable_name}")
file(DOWNLOAD
"https://github.com/linuxdeploy/${name}/releases/download/continuous/${executable_name}"
"${executable_file}" SHOW_PROGRESS)
file(CHMOD "${executable_file}" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
get_filename_component(executable_ext "${executable_file}" LAST_EXT)
if (executable_ext STREQUAL ".AppImage")
message(STATUS "Extracting ${executable_name}")
execute_process(
COMMAND "${executable_file}" --appimage-extract
WORKING_DIRECTORY "${base_dir}")
else()
message(STATUS "Copying ${executable_name}")
file(COPY "${executable_file}" DESTINATION "${base_dir}/squashfs-root/usr/bin/")
endif()
endif()
endfunction()
# Adds a target to the bundle target, packing in required libraries.
# If in_place is true, the bundling will be done in-place as part of the specified target.
function(bundle_target_internal target_name in_place)
# Create base bundle target if it does not exist.
if (NOT in_place AND NOT TARGET bundle)
message(STATUS "Creating base bundle target")
add_custom_target(bundle)
add_custom_command(
TARGET bundle
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bundle/")
add_custom_command(
TARGET bundle
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/license.txt" "${CMAKE_BINARY_DIR}/bundle/")
add_custom_command(
TARGET bundle
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/README.md" "${CMAKE_BINARY_DIR}/bundle/")
add_custom_command(
TARGET bundle
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/dist/scripting" "${CMAKE_BINARY_DIR}/bundle/scripting")
endif()
set(BUNDLE_EXECUTABLE_PATH "$<TARGET_FILE:${target_name}>")
if (target_name MATCHES ".*qt")
set(BUNDLE_QT ON)
if (APPLE)
# For Qt targets on Apple, expect an app bundle.
set(BUNDLE_EXECUTABLE_PATH "$<TARGET_BUNDLE_DIR:${target_name}>")
endif()
else()
set(BUNDLE_QT OFF)
endif()
# Build a list of library search paths from prefix paths.
foreach(prefix_path IN LISTS CMAKE_PREFIX_PATH CMAKE_SYSTEM_PREFIX_PATH)
if (WIN32)
list(APPEND BUNDLE_LIBRARY_PATHS "${prefix_path}/bin")
endif()
list(APPEND BUNDLE_LIBRARY_PATHS "${prefix_path}/lib")
endforeach()
foreach(library_path IN LISTS CMAKE_SYSTEM_LIBRARY_PATH)
list(APPEND BUNDLE_LIBRARY_PATHS "${library_path}")
endforeach()
# On Linux, prepare linuxdeploy and any required plugins.
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(LINUXDEPLOY_BASE "${CMAKE_BINARY_DIR}/externals/linuxdeploy")
# Download plugins first so they don't overwrite linuxdeploy's AppRun file.
download_linuxdeploy_component("${LINUXDEPLOY_BASE}" "linuxdeploy-plugin-qt" "linuxdeploy-plugin-qt-x86_64.AppImage")
download_linuxdeploy_component("${LINUXDEPLOY_BASE}" "linuxdeploy-plugin-checkrt" "linuxdeploy-plugin-checkrt-x86_64.sh")
download_linuxdeploy_component("${LINUXDEPLOY_BASE}" "linuxdeploy" "linuxdeploy-x86_64.AppImage")
set(EXTRA_BUNDLE_ARGS "-DLINUXDEPLOY=${LINUXDEPLOY_BASE}/squashfs-root/AppRun")
endif()
if (in_place)
message(STATUS "Adding in-place bundling to ${target_name}")
set(DEST_TARGET ${target_name})
else()
message(STATUS "Adding ${target_name} to bundle target")
set(DEST_TARGET bundle)
add_dependencies(bundle ${target_name})
endif()
add_custom_command(TARGET ${DEST_TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND}
"-DCMAKE_PREFIX_PATH=\"${CMAKE_PREFIX_PATH}\""
"-DBUNDLE_TARGET_EXECUTE=1"
"-DTARGET=${target_name}"
"-DSOURCE_PATH=${CMAKE_SOURCE_DIR}"
"-DBINARY_PATH=${CMAKE_BINARY_DIR}"
"-DEXECUTABLE_PATH=${BUNDLE_EXECUTABLE_PATH}"
"-DBUNDLE_LIBRARY_PATHS=\"${BUNDLE_LIBRARY_PATHS}\""
"-DBUNDLE_QT=${BUNDLE_QT}"
"-DIN_PLACE=${in_place}"
${EXTRA_BUNDLE_ARGS}
-P "${CMAKE_SOURCE_DIR}/CMakeModules/BundleTarget.cmake"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
endfunction()
# Adds a target to the bundle target, packing in required libraries.
function(bundle_target target_name)
bundle_target_internal("${target_name}" OFF)
endfunction()
# Bundles the target in-place, packing in required libraries.
function(bundle_target_in_place target_name)
bundle_target_internal("${target_name}" ON)
endfunction()
endif()

View File

@ -1,11 +0,0 @@
function(copy_citra_FFmpeg_deps target_dir)
include(WindowsCopyFiles)
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
windows_copy_files(${target_dir} ${FFMPEG_DIR}/bin ${DLL_DEST}
avcodec*.dll
avformat*.dll
avutil*.dll
swresample*.dll
swscale*.dll
)
endfunction(copy_citra_FFmpeg_deps)

View File

@ -1,6 +0,0 @@
function(copy_citra_openssl_deps target_dir)
include(WindowsCopyFiles)
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
windows_copy_files(${target_dir} ${OPENSSL_DLL_DIR} ${DLL_DEST} libcrypto-1_1-x64.dll)
windows_copy_files(${target_dir} ${OPENSSL_DLL_DIR} ${DLL_DEST} libssl-1_1-x64.dll)
endfunction(copy_citra_openssl_deps)

View File

@ -1,47 +0,0 @@
function(copy_citra_Qt5_deps target_dir)
include(WindowsCopyFiles)
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin")
set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/")
set(Qt5_MEDIASERVICE_DIR "${Qt5_DIR}/../../../plugins/mediaservice/")
set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")
set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")
set(PLATFORMS ${DLL_DEST}plugins/platforms/)
set(MEDIASERVICE ${DLL_DEST}plugins/mediaservice/)
set(STYLES ${DLL_DEST}plugins/styles/)
set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
icudt*.dll
icuin*.dll
icuuc*.dll
Qt5Core$<$<CONFIG:Debug>:d>.*
Qt5Gui$<$<CONFIG:Debug>:d>.*
Qt5Widgets$<$<CONFIG:Debug>:d>.*
Qt5Concurrent$<$<CONFIG:Debug>:d>.*
Qt5Multimedia$<$<CONFIG:Debug>:d>.*
Qt5Network$<$<CONFIG:Debug>:d>.*
)
windows_copy_files(citra-qt ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
windows_copy_files(citra-qt ${Qt5_MEDIASERVICE_DIR} ${MEDIASERVICE}
dsengine$<$<CONFIG:Debug>:d>.*
wmfengine$<$<CONFIG:Debug>:d>.*
)
windows_copy_files(citra-qt ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
windows_copy_files(${target_dir} ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
qgif$<$<CONFIG:Debug>:d>.dll
qicns$<$<CONFIG:Debug>:d>.dll
qico$<$<CONFIG:Debug>:d>.dll
qjpeg$<$<CONFIG:Debug>:d>.dll
qsvg$<$<CONFIG:Debug>:d>.dll
qtga$<$<CONFIG:Debug>:d>.dll
qtiff$<$<CONFIG:Debug>:d>.dll
qwbmp$<$<CONFIG:Debug>:d>.dll
qwebp$<$<CONFIG:Debug>:d>.dll
)
# Create an empty qt.conf file. Qt will detect that this file exists, and use the folder that its in as the root folder.
# This way it'll look for plugins in the root/plugins/ folder
add_custom_command(TARGET citra-qt POST_BUILD
COMMAND ${CMAKE_COMMAND} -E touch ${DLL_DEST}qt.conf
)
endfunction(copy_citra_Qt5_deps)

View File

@ -1,5 +0,0 @@
function(copy_citra_SDL_deps target_dir)
include(WindowsCopyFiles)
set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
windows_copy_files(${target_dir} ${SDL2_DLL_DIR} ${DLL_DEST} SDL2.dll)
endfunction(copy_citra_SDL_deps)

View File

@ -1,96 +1,117 @@
# This function downloads a binary library package from our external repo.
# Params:
# remote_path: path to the file to download, relative to the remote repository root
# prefix_var: name of a variable which will be set with the path to the extracted contents
function(download_bundled_external remote_path lib_name prefix_var)
get_external_prefix(${lib_name} prefix)
if (NOT EXISTS "${prefix}")
message(STATUS "Downloading binaries for ${lib_name}...")
if (WIN32)
set(repo_base "ext-windows-bin/raw/master")
elseif (APPLE)
set(repo_base "ext-macos-bin/raw/main")
else()
message(FATAL_ERROR "Bundled libraries are unsupported for this OS.")
endif()
file(DOWNLOAD
https://github.com/citra-emu/${repo_base}/${remote_path}${lib_name}.7z
"${CMAKE_BINARY_DIR}/externals/${lib_name}.7z" SHOW_PROGRESS)
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${CMAKE_BINARY_DIR}/externals/${lib_name}.7z"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
endif()
# For packages that include the /usr/local prefix, include it in the prefix path.
if (EXISTS "${prefix}/usr/local")
set(prefix "${prefix}/usr/local")
endif()
message(STATUS "Using bundled binaries at ${prefix}")
set(${prefix_var} "${prefix}" PARENT_SCOPE)
endfunction()
# This function downloads Qt using aqt.
# Params:
# target: Qt dependency to install. Specify a version number to download Qt, or "tools_(name)" for a specific build tool.
# prefix_var: Name of a variable which will be set with the path to the extracted contents.
function(download_qt_external target prefix_var)
function(download_qt target)
# Determine installation parameters for OS, architecture, and compiler
if (WIN32)
set(host "windows")
set(type "desktop")
if (MINGW)
set(arch_path "mingw81")
elseif ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND "x86_64" IN_LIST ARCHITECTURE)
set(arch "win64_mingw")
set(arch_path "mingw_64")
elseif (MSVC)
if ("arm64" IN_LIST ARCHITECTURE)
set(arch_path "msvc2019_arm64")
elseif ("x86_64" IN_LIST ARCHITECTURE)
set(arch_path "msvc2019_64")
else()
message(FATAL_ERROR "Unsupported bundled Qt architecture. Disable CITRA_USE_BUNDLED_QT and provide your own.")
message(FATAL_ERROR "Unsupported bundled Qt architecture. Enable USE_SYSTEM_QT and provide your own.")
endif()
set(arch "win64_${arch_path}")
else()
message(FATAL_ERROR "Unsupported bundled Qt toolchain. Disable CITRA_USE_BUNDLED_QT and provide your own.")
message(FATAL_ERROR "Unsupported bundled Qt toolchain. Enable USE_SYSTEM_QT and provide your own.")
endif()
set(arch "win64_${arch_path}")
elseif (APPLE)
set(host "mac")
set(arch "clang_64")
set(arch_path "macos")
if (IOS)
set(type "ios")
set(arch "ios")
set(arch_path "ios")
set(host_arch_path "macos")
else()
set(type "desktop")
set(arch "clang_64")
set(arch_path "macos")
endif()
else()
set(host "linux")
set(type "desktop")
set(arch "gcc_64")
set(arch_path "linux")
endif()
get_external_prefix(qt base_path)
file(MAKE_DIRECTORY "${base_path}")
if (target MATCHES "tools_.*")
set(prefix "${base_path}")
set(install_args install-tool --outputdir ${base_path} ${host} desktop ${target})
else()
set(prefix "${base_path}/${target}/${arch_path}")
set(install_args install-qt --outputdir ${base_path} ${host} desktop ${target} ${arch})
if (host_arch_path)
set(host_flag "--autodesktop")
set(host_prefix "${base_path}/${target}/${host_arch_path}")
endif()
set(install_args install-qt --outputdir ${base_path} ${host} ${type} ${target} ${arch} ${host_flag} -m qtmultimedia)
endif()
if (NOT EXISTS "${prefix}")
message(STATUS "Downloading binaries for Qt...")
if (WIN32)
set(aqt_path "${CMAKE_BINARY_DIR}/externals/aqt.exe")
set(aqt_path "${base_path}/aqt.exe")
file(DOWNLOAD
https://github.com/miurahr/aqtinstall/releases/download/v3.1.4/aqt.exe
${aqt_path} SHOW_PROGRESS)
execute_process(COMMAND ${aqt_path} ${install_args})
execute_process(COMMAND ${aqt_path} ${install_args}
WORKING_DIRECTORY ${base_path})
else()
# aqt does not offer binary releases for other platforms, so download and run from pip.
set(aqt_install_path "${CMAKE_BINARY_DIR}/externals/aqt")
execute_process(COMMAND python3 -m pip install --target=${aqt_install_path} aqtinstall)
execute_process(COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${aqt_install_path} python3 -m aqt ${install_args})
set(aqt_install_path "${base_path}/aqt")
file(MAKE_DIRECTORY "${aqt_install_path}")
execute_process(COMMAND python3 -m pip install --target=${aqt_install_path} aqtinstall
WORKING_DIRECTORY ${base_path})
execute_process(COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${aqt_install_path} python3 -m aqt ${install_args}
WORKING_DIRECTORY ${base_path})
endif()
endif()
message(STATUS "Using downloaded Qt binaries at ${prefix}")
set(${prefix_var} "${prefix}" PARENT_SCOPE)
# Add the Qt prefix path so CMake can locate it.
list(APPEND CMAKE_PREFIX_PATH "${prefix}")
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
if (DEFINED host_prefix)
message(STATUS "Using downloaded host Qt binaries at ${host_prefix}")
set(QT_HOST_PATH "${host_prefix}" CACHE STRING "")
endif()
endfunction()
function(download_moltenvk)
if (IOS)
set(MOLTENVK_PLATFORM "iOS")
else()
set(MOLTENVK_PLATFORM "macOS")
endif()
set(MOLTENVK_DIR "${CMAKE_BINARY_DIR}/externals/MoltenVK")
set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar")
if (NOT EXISTS ${MOLTENVK_DIR})
if (NOT EXISTS ${MOLTENVK_TAR})
file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/latest/download/MoltenVK-all.tar
${MOLTENVK_TAR} SHOW_PROGRESS)
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${MOLTENVK_TAR}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
endif()
# Add the MoltenVK library path to the prefix so find_library can locate it.
list(APPEND CMAKE_PREFIX_PATH "${MOLTENVK_DIR}/MoltenVK/dylib/${MOLTENVK_PLATFORM}")
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE)
endfunction()
function(get_external_prefix lib_name prefix_var)

View File

@ -0,0 +1,65 @@
# Gets a UTC timstamp and sets the provided variable to it
function(get_timestamp _var)
string(TIMESTAMP timestamp UTC)
set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction()
get_timestamp(BUILD_DATE)
list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/externals/cmake-modules")
if (EXISTS "${SRC_DIR}/.git/objects")
# Find the package here with the known path so that the GetGit commands can find it as well
find_package(Git QUIET PATHS "${GIT_EXECUTABLE}")
# only use Git to check revision info when source is obtained via Git
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REF_SPEC GIT_REV)
git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
elseif (EXISTS "${SRC_DIR}/GIT-COMMIT" AND EXISTS "${SRC_DIR}/GIT-TAG")
# unified source archive
file(READ "${SRC_DIR}/GIT-COMMIT" GIT_REV_RAW LIMIT 64)
string(STRIP "${GIT_REV_RAW}" GIT_REV)
string(SUBSTRING "${GIT_REV_RAW}" 0 9 GIT_DESC)
set(GIT_BRANCH "HEAD")
else()
# self-packed archive?
set(GIT_REV "UNKNOWN")
set(GIT_DESC "UNKNOWN")
set(GIT_BRANCH "UNKNOWN")
endif()
string(SUBSTRING "${GIT_REV}" 0 7 GIT_SHORT_REV)
# Generate cpp with Git revision from template
# Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well
set(REPO_NAME "")
set(BUILD_VERSION "0")
set(BUILD_FULLNAME "${GIT_SHORT_REV}")
if (DEFINED ENV{CI})
if (DEFINED ENV{GITHUB_ACTIONS})
set(BUILD_REPOSITORY $ENV{GITHUB_REPOSITORY})
set(BUILD_TAG $ENV{GITHUB_REF_NAME})
endif()
# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "citra-emu/citra-?(.*)" OUTVAR ${BUILD_REPOSITORY})
if ("${CMAKE_MATCH_COUNT}" GREATER 0)
# capitalize the first letter of each word in the repo name.
string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1})
foreach(WORD ${REPO_NAME_LIST})
string(SUBSTRING ${WORD} 0 1 FIRST_LETTER)
string(SUBSTRING ${WORD} 1 -1 REMAINDER)
string(TOUPPER ${FIRST_LETTER} FIRST_LETTER)
set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER}")
endforeach()
string(REGEX MATCH "${CMAKE_MATCH_1}-([0-9]+)" OUTVAR ${BUILD_TAG})
if (${CMAKE_MATCH_COUNT} GREATER 0)
set(BUILD_VERSION ${CMAKE_MATCH_1})
endif()
if (BUILD_VERSION)
set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION}")
else()
set(BUILD_FULLNAME "")
endif()
endif()
endif()

View File

@ -1,55 +1,5 @@
# Gets a UTC timstamp and sets the provided variable to it
function(get_timestamp _var)
string(TIMESTAMP timestamp UTC)
set(${_var} "${timestamp}" PARENT_SCOPE)
endfunction()
list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/externals/cmake-modules")
# Find the package here with the known path so that the GetGit commands can find it as well
find_package(Git QUIET PATHS "${GIT_EXECUTABLE}")
# generate git/build information
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REF_SPEC GIT_REV)
git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
get_timestamp(BUILD_DATE)
# Generate cpp with Git revision from template
# Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well
set(REPO_NAME "")
set(BUILD_VERSION "0")
if (DEFINED ENV{CI})
if (DEFINED ENV{GITHUB_ACTIONS})
set(BUILD_REPOSITORY $ENV{GITHUB_REPOSITORY})
set(BUILD_TAG $ENV{GITHUB_REF_NAME})
endif()
# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "citra-emu/citra-?(.*)" OUTVAR ${BUILD_REPOSITORY})
if ("${CMAKE_MATCH_COUNT}" GREATER 0)
# capitalize the first letter of each word in the repo name.
string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1})
foreach(WORD ${REPO_NAME_LIST})
string(SUBSTRING ${WORD} 0 1 FIRST_LETTER)
string(SUBSTRING ${WORD} 1 -1 REMAINDER)
string(TOUPPER ${FIRST_LETTER} FIRST_LETTER)
set(REPO_NAME "${REPO_NAME}${FIRST_LETTER}${REMAINDER}")
endforeach()
string(REGEX MATCH "${CMAKE_MATCH_1}-([0-9]+)" OUTVAR ${BUILD_TAG})
if (${CMAKE_MATCH_COUNT} GREATER 0)
set(BUILD_VERSION ${CMAKE_MATCH_1})
endif()
if (BUILD_VERSION)
# This leaves a trailing space on the last word, but we actually want that
# because of how it's styled in the title bar.
set(BUILD_FULLNAME "${REPO_NAME} ${BUILD_VERSION} ")
else()
set(BUILD_FULLNAME "")
endif()
endif()
endif()
list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/CMakeModules")
include(GenerateBuildInfo)
# The variable SRC_DIR must be passed into the script (since it uses the current build directory for all values of CMAKE_*_DIR)
set(VIDEO_CORE "${SRC_DIR}/src/video_core")

View File

@ -1,12 +0,0 @@
# buildcache wrapper
OPTION(CITRA_USE_CCACHE "Use buildcache for compilation" OFF)
IF(CITRA_USE_CCACHE)
FIND_PROGRAM(CCACHE buildcache)
IF (CCACHE)
MESSAGE(STATUS "Using buildcache found in PATH")
SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
ELSE(CCACHE)
MESSAGE(WARNING "CITRA_USE_CCACHE enabled, but no buildcache executable found")
ENDIF(CCACHE)
ENDIF(CITRA_USE_CCACHE)

View File

@ -1,54 +0,0 @@
SET(MINGW_PREFIX /usr/x86_64-w64-mingw32/)
SET(CMAKE_SYSTEM_NAME Windows)
SET(CMAKE_SYSTEM_PROCESSOR x86_64)
# Actually a hack, w/o this will cause some strange errors
SET(CMAKE_HOST_WIN32 TRUE)
SET(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX})
SET(SDL2_PATH ${MINGW_PREFIX})
SET(MINGW_TOOL_PREFIX ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-)
# Specify the cross compiler
SET(CMAKE_C_COMPILER ${MINGW_TOOL_PREFIX}gcc)
SET(CMAKE_CXX_COMPILER ${MINGW_TOOL_PREFIX}g++)
SET(CMAKE_RC_COMPILER ${MINGW_TOOL_PREFIX}windres)
# Mingw tools
SET(STRIP ${MINGW_TOOL_PREFIX}strip)
SET(WINDRES ${MINGW_TOOL_PREFIX}windres)
SET(ENV{PKG_CONFIG} ${MINGW_TOOL_PREFIX}pkg-config)
# ccache wrapper
OPTION(CITRA_USE_CCACHE "Use ccache for compilation" OFF)
IF(CITRA_USE_CCACHE)
FIND_PROGRAM(CCACHE ccache)
IF (CCACHE)
MESSAGE(STATUS "Using ccache found in PATH")
SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
ELSE(CCACHE)
MESSAGE(WARNING "CITRA_USE_CCACHE enabled, but no ccache found")
ENDIF(CCACHE)
ENDIF(CITRA_USE_CCACHE)
# Search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Echo modified cmake vars to screen for debugging purposes
IF(NOT DEFINED ENV{MINGW_DEBUG_INFO})
MESSAGE("")
MESSAGE("Custom cmake vars: (blank = system default)")
MESSAGE("-----------------------------------------")
MESSAGE("* CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}")
MESSAGE("* CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}")
MESSAGE("* CMAKE_RC_COMPILER : ${CMAKE_RC_COMPILER}")
MESSAGE("* WINDRES : ${WINDRES}")
MESSAGE("* ENV{PKG_CONFIG} : $ENV{PKG_CONFIG}")
MESSAGE("* STRIP : ${STRIP}")
MESSAGE("* CITRA_USE_CCACHE : ${CITRA_USE_CCACHE}")
MESSAGE("")
# So that the debug info only appears once
SET(ENV{MINGW_DEBUG_INFO} SHOWN)
ENDIF()

View File

@ -2,45 +2,49 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string></string>
<key>CFBundleIconFile</key>
<string>citra.icns</string>
<key>CFBundleIdentifier</key>
<string>com.citra-emu.citra</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string></string>
<!-- Templated data -->
<key>CFBundleName</key>
<string>Citra</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string></string>
<key>CFBundleSignature</key>
<string>????</string>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleVersion</key>
<string></string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSRequiresCarbon</key>
<true/>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>NSHumanReadableCopyright</key>
<string></string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSHighResolutionCapable</key>
<string>True</string>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<!-- Fixed -->
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>NSCameraUsageDescription</key>
<string>This app requires camera access to emulate the 3DS&apos;s cameras.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access to emulate the 3DS&apos;s microphone.</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>NSHighResolutionCapable</key>
<string>True</string>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
</dict>
</plist>

42
dist/apple/LaunchScreen.storyboard vendored Normal file
View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="Y6W-OH-hqX">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="s0d-6b-0kx">
<objects>
<viewController id="Y6W-OH-hqX" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch_logo.png" translatesAutoresizingMaskIntoConstraints="NO" id="yrZ-hu-Uge">
<rect key="frame" x="-59.666666666666657" y="306" width="512.33333333333337" height="240"/>
<constraints>
<constraint firstAttribute="height" constant="240" id="VhL-hA-Bwr"/>
</constraints>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="yrZ-hu-Uge" firstAttribute="centerX" secondItem="5EZ-qb-Rvc" secondAttribute="centerX" id="1y3-Mx-a65"/>
<constraint firstItem="yrZ-hu-Uge" firstAttribute="centerY" secondItem="5EZ-qb-Rvc" secondAttribute="centerY" id="vNO-xV-EPD"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="219" y="18"/>
</scene>
</scenes>
<resources>
<image name="launch_logo.png" width="512" height="512"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>

BIN
dist/apple/launch_logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

15
dist/citra-qt.desktop vendored Normal file
View File

@ -0,0 +1,15 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=Citra
GenericName=3DS Emulator
GenericName[fr]=Émulateur 3DS
Comment=Nintendo 3DS video game console emulator
Comment[fr]=Émulateur de console de jeu Nintendo 3DS
Icon=citra
TryExec=citra-qt
Exec=citra-qt %f
Categories=Game;Emulator;Qt;
MimeType=application/x-ctr-3dsx;application/x-ctr-cci;application/x-ctr-cia;application/x-ctr-cxi;
Keywords=3DS;Nintendo;
PrefersNonDefaultGPU=true

10
dist/citra-room.desktop vendored Normal file
View File

@ -0,0 +1,10 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=Citra Room
Comment=Multiplayer room host for Citra
Icon=citra
TryExec=citra-room
Exec=citra-room %f
Categories=Game;Emulator;
Keywords=3DS;Nintendo

6
dist/citra.desktop vendored
View File

@ -7,9 +7,9 @@ GenericName[fr]=Émulateur 3DS
Comment=Nintendo 3DS video game console emulator
Comment[fr]=Émulateur de console de jeu Nintendo 3DS
Icon=citra
TryExec=citra-qt
Exec=citra-qt %f
Categories=Game;Emulator;Qt;
TryExec=citra
Exec=citra %f
Categories=Game;Emulator;
MimeType=application/x-ctr-3dsx;application/x-ctr-cci;application/x-ctr-cia;application/x-ctr-cxi;
Keywords=3DS;Nintendo;
PrefersNonDefaultGPU=true

View File

@ -1,3 +1,17 @@
QPushButton#GraphicsAPIStatusBarButton {
color: #656565;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
min-width: 60px;
min-height: 20px;
}
QPushButton#GraphicsAPIStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#3DOptionStatusBarButton {
color: #A5A5A5;
font-weight: bold;

View File

@ -1,3 +1,31 @@
QPushButton#TogglableStatusBarButton {
color: #959595;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
}
QPushButton#TogglableStatusBarButton:checked {
color: palette(text);
}
QPushButton#TogglableStatusBarButton:hover {
border: 1px solid #76797C;
}
QPushButton#GraphicsAPIStatusBarButton {
color: #656565;
border: 1px solid transparent;
background-color: transparent;
padding: 0px 3px 0px 3px;
text-align: center;
}
QPushButton#GraphicsAPIStatusBarButton:hover {
border: 1px solid #76797C;
}
QToolTip {
border: 1px solid #76797C;
background-color: #5A7566;

View File

@ -3,6 +3,8 @@
# Suppress warnings from external libraries
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
add_compile_options(/W0)
else()
add_compile_options(-w)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules)
@ -10,46 +12,42 @@ include(DownloadExternals)
include(ExternalProject)
# Boost
set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/boost")
set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost")
set(Boost_NO_SYSTEM_PATHS ON)
add_library(boost INTERFACE)
target_include_directories(boost SYSTEM INTERFACE ${Boost_INCLUDE_DIR})
if (NOT USE_SYSTEM_BOOST)
message(STATUS "Including vendored Boost library")
set(BOOST_ROOT "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "")
set(Boost_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/externals/boost" CACHE STRING "")
set(Boost_NO_SYSTEM_PATHS ON CACHE BOOL "")
add_library(boost INTERFACE)
target_include_directories(boost SYSTEM INTERFACE ${Boost_INCLUDE_DIR})
# Boost::serialization
file(GLOB boost_serialization_SRC "${CMAKE_SOURCE_DIR}/externals/boost/libs/serialization/src/*.cpp")
add_library(boost_serialization STATIC ${boost_serialization_SRC})
target_link_libraries(boost_serialization PUBLIC boost)
# Boost::iostreams
add_library(
boost_iostreams
STATIC
${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/file_descriptor.cpp
${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/mapped_file.cpp
)
target_link_libraries(boost_iostreams PUBLIC boost)
# Boost::serialization
file(GLOB boost_serialization_SRC "${CMAKE_SOURCE_DIR}/externals/boost/libs/serialization/src/*.cpp")
add_library(boost_serialization STATIC ${boost_serialization_SRC})
target_link_libraries(boost_serialization PUBLIC boost)
# Boost::iostreams
add_library(
boost_iostreams
STATIC
${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/file_descriptor.cpp
${CMAKE_SOURCE_DIR}/externals/boost/libs/iostreams/src/mapped_file.cpp
)
target_link_libraries(boost_iostreams PUBLIC boost)
# Add additional boost libs here; remember to ALIAS them in the root CMakeLists!
endif()
# Catch2
set(CATCH_INSTALL_DOCS OFF)
set(CATCH_INSTALL_EXTRAS OFF)
set(CATCH_INSTALL_DOCS OFF CACHE BOOL "")
set(CATCH_INSTALL_EXTRAS OFF CACHE BOOL "")
add_subdirectory(catch2)
# Crypto++
set(CRYPTOPP_BUILD_DOCUMENTATION OFF)
set(CRYPTOPP_BUILD_TESTING OFF)
set(CRYPTOPP_INSTALL OFF)
set(CRYPTOPP_SOURCES "${CMAKE_SOURCE_DIR}/externals/cryptopp")
set(CRYPTOPP_BUILD_DOCUMENTATION OFF CACHE BOOL "")
set(CRYPTOPP_BUILD_TESTING OFF CACHE BOOL "")
set(CRYPTOPP_INSTALL OFF CACHE BOOL "")
set(CRYPTOPP_SOURCES "${CMAKE_SOURCE_DIR}/externals/cryptopp" CACHE STRING "")
add_subdirectory(cryptopp-cmake)
# HACK: Mismatch between compilation of CryptoPP and headers used in Citra can cause runtime issues.
# Pull out the compile definitions from CryptoPP and apply them to Citra as well to fix this.
# See: https://github.com/weidai11/cryptopp/issues/1191
get_source_file_property(CRYPTOPP_COMPILE_DEFINITIONS ${CRYPTOPP_SOURCES}/cryptlib.cpp TARGET_DIRECTORY cryptopp COMPILE_DEFINITIONS)
set(CRYPTOPP_COMPILE_DEFINITIONS ${CRYPTOPP_COMPILE_DEFINITIONS} PARENT_SCOPE)
# HACK: The logic to set up the base include directory for CryptoPP does not work with Android SDK CMake 3.22.1.
# Until there is a fixed version available, this code will detect and add in the proper include if it does not exist.
if(ANDROID)
@ -80,8 +78,8 @@ endif()
# Dynarmic
if ("x86_64" IN_LIST ARCHITECTURE OR "arm64" IN_LIST ARCHITECTURE)
set(DYNARMIC_TESTS OFF)
set(DYNARMIC_FRONTENDS "A32")
set(DYNARMIC_TESTS OFF CACHE BOOL "")
set(DYNARMIC_FRONTENDS "A32" CACHE STRING "")
add_subdirectory(dynarmic EXCLUDE_FROM_ALL)
endif()
@ -93,28 +91,43 @@ endif()
# Glad
add_subdirectory(glad)
# glslang
set(SKIP_GLSLANG_INSTALL ON CACHE BOOL "")
set(ENABLE_GLSLANG_BINARIES OFF CACHE BOOL "")
set(ENABLE_SPVREMAPPER OFF CACHE BOOL "")
set(ENABLE_CTEST OFF CACHE BOOL "")
set(ENABLE_HLSL OFF CACHE BOOL "")
add_subdirectory(glslang)
# inih
add_subdirectory(inih)
# MicroProfile
add_library(microprofile INTERFACE)
target_include_directories(microprofile INTERFACE ./microprofile)
target_include_directories(microprofile SYSTEM INTERFACE ./microprofile)
# Nihstro
add_library(nihstro-headers INTERFACE)
target_include_directories(nihstro-headers INTERFACE ./nihstro/include)
target_include_directories(nihstro-headers SYSTEM INTERFACE ./nihstro/include)
if (MSVC)
target_compile_options(nihstro-headers INTERFACE /W0)
# TODO: For some reason MSVC still applies this warning even with /W0 for externals.
target_compile_options(nihstro-headers INTERFACE /wd4715)
endif()
# Open Source Archives
add_subdirectory(open_source_archives)
# SoundTouch
# Dynamic library headers
add_subdirectory(library-headers EXCLUDE_FROM_ALL)
# SoundTouch
set(INTEGER_SAMPLES ON CACHE BOOL "")
set(SOUNDSTRETCH OFF CACHE BOOL "")
set(SOUNDTOUCH_DLL OFF CACHE BOOL "")
add_subdirectory(soundtouch)
add_subdirectory(soundtouch EXCLUDE_FROM_ALL)
# sirit
add_subdirectory(sirit EXCLUDE_FROM_ALL)
# Teakra
add_subdirectory(teakra EXCLUDE_FROM_ALL)
@ -124,6 +137,13 @@ if (ENABLE_SDL2 AND NOT USE_SYSTEM_SDL2)
add_subdirectory(sdl2)
endif()
# libusb
if (ENABLE_LIBUSB AND NOT USE_SYSTEM_LIBUSB)
add_subdirectory(libusb)
set(LIBUSB_INCLUDE_DIR "" PARENT_SCOPE)
set(LIBUSB_LIBRARIES usb PARENT_SCOPE)
endif()
# Zstandard
set(ZSTD_LEGACY_SUPPORT OFF)
set(ZSTD_BUILD_PROGRAMS OFF)
@ -138,6 +158,8 @@ target_include_directories(enet INTERFACE ./enet/include)
# Cubeb
if (ENABLE_CUBEB)
set(BUILD_TESTS OFF CACHE BOOL "")
set(BUILD_TOOLS OFF CACHE BOOL "")
set(BUNDLE_SPEEX ON CACHE BOOL "")
add_subdirectory(cubeb EXCLUDE_FROM_ALL)
endif()
@ -151,33 +173,38 @@ endif()
add_library(json-headers INTERFACE)
target_include_directories(json-headers INTERFACE ./json)
if (ENABLE_WEB_SERVICE)
# OpenSSL
if (USE_SYSTEM_OPENSSL)
find_package(OpenSSL 1.1)
if (OPENSSL_FOUND)
set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
else()
# LibreSSL
set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "")
set(OPENSSLDIR "/etc/ssl/")
add_subdirectory(libressl EXCLUDE_FROM_ALL)
target_include_directories(ssl INTERFACE ./libressl/include)
target_compile_definitions(ssl PRIVATE -DHAVE_INET_NTOP)
get_directory_property(OPENSSL_LIBRARIES
DIRECTORY libressl
DEFINITION OPENSSL_LIBS)
endif()
endif()
if(ANDROID)
add_subdirectory(android-ifaddrs)
endif()
if (NOT OPENSSL_FOUND)
# LibreSSL
set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "")
set(OPENSSLDIR "/etc/ssl/")
add_subdirectory(libressl EXCLUDE_FROM_ALL)
target_include_directories(ssl INTERFACE ./libressl/include)
target_compile_definitions(ssl PRIVATE -DHAVE_INET_NTOP)
get_directory_property(OPENSSL_LIBRARIES
DIRECTORY libressl
DEFINITION OPENSSL_LIBS)
endif()
# httplib
add_library(httplib INTERFACE)
target_include_directories(httplib INTERFACE ./httplib)
target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
# httplib
add_library(httplib INTERFACE)
target_include_directories(httplib INTERFACE ./httplib)
target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
# cpp-jwt
if(ANDROID)
add_subdirectory(android-ifaddrs)
endif()
# cpp-jwt
if (ENABLE_WEB_SERVICE)
add_library(cpp-jwt INTERFACE)
target_include_directories(cpp-jwt INTERFACE ./cpp-jwt/include)
target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
@ -205,3 +232,11 @@ if (ENABLE_OPENAL)
set(LIBTYPE "STATIC" CACHE STRING "")
add_subdirectory(openal-soft EXCLUDE_FROM_ALL)
endif()
# VMA
add_library(vma INTERFACE)
target_include_directories(vma SYSTEM INTERFACE ./vma/include)
# vulkan-headers
add_library(vulkan-headers INTERFACE)
target_include_directories(vulkan-headers SYSTEM INTERFACE ./vulkan-headers/include)

View File

@ -1,192 +0,0 @@
# FindFFmpeg
# ----------
#
# Find the native FFmpeg includes and libraries
#
# This module defines the following variables:
#
# FFmpeg_INCLUDE_<component>: where to find <component>.h
# FFmpeg_LIBRARY_<component>: where to find the <component> library
# FFmpeg_INCLUDES: aggregate all the include paths
# FFmpeg_LIBRARIES: aggregate all the paths to the libraries
# FFmpeg_FOUND: True if all components have been found
#
# This module defines the following targets, which are prefered over variables:
#
# FFmpeg::<component>: Target to use <component> directly, with include path,
# library and dependencies set up. If you are using a static build, you are
# responsible for adding any external dependencies (such as zlib, bzlib...).
#
# <component> can be one of:
# avcodec
# avdevice
# avfilter
# avformat
# postproc
# swresample
# swscale
#
set(_FFmpeg_ALL_COMPONENTS
avcodec
avdevice
avfilter
avformat
avutil
postproc
swresample
swscale
)
set(_FFmpeg_DEPS_avcodec avutil)
set(_FFmpeg_DEPS_avdevice avcodec avformat avutil)
set(_FFmpeg_DEPS_avfilter avutil)
set(_FFmpeg_DEPS_avformat avcodec avutil)
set(_FFmpeg_DEPS_postproc avutil)
set(_FFmpeg_DEPS_swresample avutil)
set(_FFmpeg_DEPS_swscale avutil)
function(find_ffmpeg LIBNAME)
if(DEFINED ENV{FFMPEG_DIR})
set(FFMPEG_DIR $ENV{FFMPEG_DIR})
endif()
if(FFMPEG_DIR)
list(APPEND INCLUDE_PATHS
${FFMPEG_DIR}
${FFMPEG_DIR}/ffmpeg
${FFMPEG_DIR}/lib${LIBNAME}
${FFMPEG_DIR}/include/lib${LIBNAME}
${FFMPEG_DIR}/include/ffmpeg
${FFMPEG_DIR}/include
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
list(APPEND LIB_PATHS
${FFMPEG_DIR}
${FFMPEG_DIR}/lib
${FFMPEG_DIR}/lib${LIBNAME}
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
else()
list(APPEND INCLUDE_PATHS
/usr/local/include/ffmpeg
/usr/local/include/lib${LIBNAME}
/usr/include/ffmpeg
/usr/include/lib${LIBNAME}
/usr/include/ffmpeg/lib${LIBNAME}
)
list(APPEND LIB_PATHS
/usr/local/lib
/usr/lib
)
endif()
find_path(FFmpeg_INCLUDE_${LIBNAME} lib${LIBNAME}/${LIBNAME}.h
HINTS ${INCLUDE_PATHS}
)
find_library(FFmpeg_LIBRARY_${LIBNAME} ${LIBNAME}
HINTS ${LIB_PATHS}
)
if(NOT FFMPEG_DIR AND (NOT FFmpeg_LIBRARY_${LIBNAME} OR NOT FFmpeg_INCLUDE_${LIBNAME}))
# Didn't find it in the usual paths, try pkg-config
find_package(PkgConfig QUIET)
pkg_check_modules(FFmpeg_PKGCONFIG_${LIBNAME} QUIET lib${LIBNAME})
find_path(FFmpeg_INCLUDE_${LIBNAME} lib${LIBNAME}/${LIBNAME}.h
${FFmpeg_PKGCONFIG_${LIBNAME}_INCLUDE_DIRS}
)
find_library(FFmpeg_LIBRARY_${LIBNAME} ${LIBNAME}
${FFmpeg_PKGCONFIG_${LIBNAME}_LIBRARY_DIRS}
)
endif()
if(FFmpeg_INCLUDE_${LIBNAME} AND FFmpeg_LIBRARY_${LIBNAME})
set(FFmpeg_INCLUDE_${LIBNAME} "${FFmpeg_INCLUDE_${LIBNAME}}" PARENT_SCOPE)
set(FFmpeg_LIBRARY_${LIBNAME} "${FFmpeg_LIBRARY_${LIBNAME}}" PARENT_SCOPE)
# Extract FFmpeg version from version.h
foreach(v MAJOR MINOR MICRO)
set(FFmpeg_${LIBNAME}_VERSION_${v} 0)
endforeach()
string(TOUPPER ${LIBNAME} LIBNAME_UPPER)
file(STRINGS "${FFmpeg_INCLUDE_${LIBNAME}}/lib${LIBNAME}/version.h" _FFmpeg_VERSION_H_CONTENTS REGEX "#define LIB${LIBNAME_UPPER}_VERSION_(MAJOR|MINOR|MICRO) ")
if (EXISTS "${FFmpeg_INCLUDE_${LIBNAME}}/lib${LIBNAME}/version_major.h")
file(STRINGS "${FFmpeg_INCLUDE_${LIBNAME}}/lib${LIBNAME}/version_major.h" _FFmpeg_MAJOR_VERSION_H_CONTENTS REGEX "#define LIB${LIBNAME_UPPER}_VERSION_MAJOR ")
string(APPEND _FFmpeg_VERSION_H_CONTENTS "\n" ${_FFmpeg_MAJOR_VERSION_H_CONTENTS})
endif()
set(_FFmpeg_VERSION_REGEX "([0-9]+)")
foreach(v MAJOR MINOR MICRO)
if("${_FFmpeg_VERSION_H_CONTENTS}" MATCHES "#define LIB${LIBNAME_UPPER}_VERSION_${v}[\\t ]+${_FFmpeg_VERSION_REGEX}")
set(FFmpeg_${LIBNAME}_VERSION_${v} "${CMAKE_MATCH_1}")
endif()
endforeach()
set(FFmpeg_${LIBNAME}_VERSION "${FFmpeg_${LIBNAME}_VERSION_MAJOR}.${FFmpeg_${LIBNAME}_VERSION_MINOR}.${FFmpeg_${LIBNAME}_VERSION_MICRO}")
set(FFmpeg_${c}_VERSION "${FFmpeg_${LIBNAME}_VERSION}" PARENT_SCOPE)
unset(_FFmpeg_VERSION_REGEX)
unset(_FFmpeg_VERSION_H_CONTENTS)
set(FFmpeg_${c}_FOUND TRUE PARENT_SCOPE)
if(NOT FFmpeg_FIND_QUIETLY)
message("-- Found ${LIBNAME}: ${FFmpeg_INCLUDE_${LIBNAME}} ${FFmpeg_LIBRARY_${LIBNAME}} (version: ${FFmpeg_${LIBNAME}_VERSION})")
endif()
endif()
endfunction()
foreach(c ${_FFmpeg_ALL_COMPONENTS})
find_ffmpeg(${c})
endforeach()
foreach(c ${_FFmpeg_ALL_COMPONENTS})
if(FFmpeg_${c}_FOUND)
list(APPEND FFmpeg_INCLUDES ${FFmpeg_INCLUDE_${c}})
list(APPEND FFmpeg_LIBRARIES ${FFmpeg_LIBRARY_${c}})
add_library(FFmpeg::${c} IMPORTED UNKNOWN)
set_target_properties(FFmpeg::${c} PROPERTIES
IMPORTED_LOCATION ${FFmpeg_LIBRARY_${c}}
INTERFACE_INCLUDE_DIRECTORIES ${FFmpeg_INCLUDE_${c}}
)
if(APPLE)
set_target_properties(FFmpeg::${c} PROPERTIES
MACOSX_RPATH 1
)
endif()
if(_FFmpeg_DEPS_${c})
set(deps)
foreach(dep ${_FFmpeg_DEPS_${c}})
list(APPEND deps FFmpeg::${dep})
endforeach()
set_target_properties(FFmpeg::${c} PROPERTIES
INTERFACE_LINK_LIBRARIES "${deps}"
)
unset(deps)
endif()
endif()
endforeach()
if(FFmpeg_INCLUDES)
list(REMOVE_DUPLICATES FFmpeg_INCLUDES)
endif()
foreach(c ${FFmpeg_FIND_COMPONENTS})
list(APPEND _FFmpeg_REQUIRED_VARS FFmpeg_INCLUDE_${c} FFmpeg_LIBRARY_${c})
endforeach()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(FFmpeg
REQUIRED_VARS ${_FFmpeg_REQUIRED_VARS}
HANDLE_COMPONENTS
)
foreach(c ${_FFmpeg_ALL_COMPONENTS})
unset(_FFmpeg_DEPS_${c})
endforeach()
unset(_FFmpeg_ALL_COMPONENTS)
unset(_FFmpeg_REQUIRED_VARS)

View File

@ -1,28 +0,0 @@
# Copyright 2016 Citra Emulator Project
# Licensed under GPLv2 or any later version
# Refer to the license.txt file included.
# This file provides the function windows_copy_files.
# This is only valid on Windows.
# Include guard
if(__windows_copy_files)
return()
endif()
set(__windows_copy_files YES)
# Any number of files to copy from SOURCE_DIR to DEST_DIR can be specified after DEST_DIR.
# This copying happens post-build.
function(windows_copy_files TARGET SOURCE_DIR DEST_DIR)
# windows commandline expects the / to be \ so switch them
string(REPLACE "/" "\\\\" SOURCE_DIR ${SOURCE_DIR})
string(REPLACE "/" "\\\\" DEST_DIR ${DEST_DIR})
# /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output
# cmake adds an extra check for command success which doesn't work too well with robocopy
# so trick it into thinking the command was successful with the || cmd /c "exit /b 0"
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${DEST_DIR}
COMMAND robocopy ${SOURCE_DIR} ${DEST_DIR} ${ARGN} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0"
)
endfunction()

1
externals/glslang vendored Submodule

Submodule externals/glslang added at 1e4955adbc

View File

@ -233,6 +233,12 @@ using socket_t = int;
#undef X509_EXTENSIONS
#undef PKCS7_SIGNER_INFO
// libressl will warn without this, which becomes an error.
#undef OCSP_REQUEST
#undef OCSP_RESPONSE
#undef PKCS7_ISSUER_AND_SERIAL
#undef __WINCRYPT_H__
#ifdef _MSC_VER
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "cryptui.lib")

View File

@ -0,0 +1,48 @@
add_library(library-headers INTERFACE)
# libfdk-aac headers
find_path(FDK_AAC_INCLUDES NAMES fdk-aac/aacdecoder_lib.h)
if (FDK_AAC_INCLUDES STREQUAL "FDK_AAC_INCLUDES-NOTFOUND")
message(STATUS "fdk_aac headers not found, using bundled headers.")
target_include_directories(library-headers INTERFACE ./library-headers/fdk-aac/include)
else()
message(STATUS "Using headers from system fdk_aac")
target_include_directories(library-headers SYSTEM INTERFACE ${FDK_AAC_INCLUDES})
endif()
# FFmpeg headers
find_path(AVUTIL_INCLUDES NAMES libavutil/avutil.h)
find_path(AVCODEC_INCLUDES NAMES libavcodec/avcodec.h)
find_path(AVFORMAT_INCLUDES NAMES libavformat/avformat.h)
find_path(AVFILTER_INCLUDES NAMES libavfilter/avfilter.h)
find_path(SWRESAMPLE_INCLUDES NAMES libswresample/swresample.h)
# Make sure all the headers are found and from the same place, so we don't
# have missing or mismatched components.
if (AVUTIL_INCLUDES STREQUAL "AVUTIL_INCLUDES-NOTFOUND"
OR NOT AVCODEC_INCLUDES STREQUAL AVUTIL_INCLUDES
OR NOT AVFORMAT_INCLUDES STREQUAL AVUTIL_INCLUDES
OR NOT AVFILTER_INCLUDES STREQUAL AVUTIL_INCLUDES
OR NOT SWRESAMPLE_INCLUDES STREQUAL AVUTIL_INCLUDES)
message(STATUS "Complete FFmpeg headers not found, using bundled headers.")
target_include_directories(library-headers INTERFACE ./library-headers/ffmpeg/include)
else()
# Extract libavutil version from header.
file(STRINGS "${AVUTIL_INCLUDES}/libavutil/version.h" AVUTIL_VERSION_DATA
REGEX "#define LIBAVUTIL_VERSION_(MAJOR|MINOR|MICRO) ")
set(AVUTIL_VERSION_REGEX "([0-9]+)")
foreach(v MAJOR MINOR MICRO)
if("${AVUTIL_VERSION_DATA}" MATCHES "#define LIBAVUTIL_VERSION_${v}[\\t ]+${AVUTIL_VERSION_REGEX}")
set(AVUTIL_VERSION_${v} "${CMAKE_MATCH_1}")
endif()
endforeach()
set(AVUTIL_VERSION "${AVUTIL_VERSION_MAJOR}.${AVUTIL_VERSION_MINOR}.${AVUTIL_VERSION_MICRO}")
message(STATUS "Detected FFmpeg libavutil version is ${AVUTIL_VERSION}")
if ("${AVUTIL_VERSION}" VERSION_LESS "56.30.100")
message(WARNING "System FFmpeg version is too low (< 4.2), using bundled headers.")
target_include_directories(library-headers INTERFACE ./library-headers/ffmpeg/include)
else()
message(STATUS "Using headers from system FFmpeg")
target_include_directories(library-headers SYSTEM INTERFACE ${AVUTIL_INCLUDES})
endif()
endif()

View File

@ -4,7 +4,6 @@ if(MSVC)
endif()
add_library(usb STATIC EXCLUDE_FROM_ALL
libusb/libusb/core.c
libusb/libusb/core.c
libusb/libusb/descriptor.c
libusb/libusb/hotplug.c
@ -42,10 +41,9 @@ endif()
if(WIN32 OR CYGWIN)
target_sources(usb PRIVATE
libusb/libusb/os/threads_windows.c
libusb/libusb/os/windows_winusb.c
libusb/libusb/os/windows_usbdk.c
libusb/libusb/os/windows_nt_common.c
libusb/libusb/os/windows_common.c
)
set(OS_WINDOWS TRUE)
elseif(APPLE)
@ -54,10 +52,12 @@ elseif(APPLE)
)
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
find_library(IOKIT_LIBRARY IOKit)
find_library(SECURITY_LIBRARY Security)
find_library(OBJC_LIBRARY objc)
target_link_libraries(usb PRIVATE
${COREFOUNDATION_LIBRARY}
${IOKIT_LIBRARY}
${SECURITY_LIBRARY}
${OBJC_LIBRARY}
)
set(OS_DARWIN TRUE)
@ -102,7 +102,7 @@ endif()
if(UNIX)
target_sources(usb PRIVATE
libusb/libusb/os/poll_posix.c
libusb/libusb/os/events_posix.c
libusb/libusb/os/threads_posix.c
)
find_package(Threads REQUIRED)
@ -112,12 +112,13 @@ if(UNIX)
if(CMAKE_THREAD_LIBS_INIT)
target_link_libraries(usb PRIVATE "${CMAKE_THREAD_LIBS_INIT}")
endif()
set(THREADS_POSIX TRUE)
set(PLATFORM_POSIX TRUE)
elseif(WIN32)
target_sources(usb PRIVATE
libusb/libusb/os/poll_windows.c
libusb/libusb/os/events_windows.c
libusb/libusb/os/threads_windows.c
)
set(PLATFORM_WINDOWS TRUE)
endif()
include(CheckFunctionExists)
@ -127,7 +128,8 @@ check_include_files(asm/types.h HAVE_ASM_TYPES_H)
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
check_include_files(linux/filter.h HAVE_LINUX_FILTER_H)
check_include_files(linux/netlink.h HAVE_LINUX_NETLINK_H)
check_include_files(poll.h HAVE_POLL_H)
check_function_exists(eventfd HAVE_EVENTFD)
check_function_exists(timerfd_create HAVE_TIMERFD)
check_include_files(signal.h HAVE_SIGNAL_H)
check_include_files(strings.h HAVE_STRINGS_H)
check_type_size("struct timespec" STRUCT_TIMESPEC)
@ -136,17 +138,6 @@ check_include_files(syslog.h HAVE_SYSLOG_H)
check_include_files(sys/socket.h HAVE_SYS_SOCKET_H)
check_include_files(sys/time.h HAVE_SYS_TIME_H)
check_include_files(sys/types.h HAVE_SYS_TYPES_H)
set(CMAKE_EXTRA_INCLUDE_FILES poll.h)
check_type_size("nfds_t" nfds_t)
unset(CMAKE_EXTRA_INCLUDE_FILES)
if(HAVE_NFDS_T)
set(POLL_NFDS_TYPE "nfds_t")
else()
set(POLL_NFDS_TYPE "unsigned int")
endif()
check_include_files(sys/timerfd.h USBI_TIMERFD_AVAILABLE)
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
configure_file(config.h.in config.h)

View File

@ -26,8 +26,11 @@
/* Define to 1 if you have the <linux/netlink.h> header file. */
#cmakedefine HAVE_LINUX_NETLINK_H 1
/* Define to 1 if you have the <poll.h> header file. */
#cmakedefine HAVE_POLL_H 1
/* Define to 1 if you have eventfd support. */
#cmakedefine HAVE_EVENTFD 1
/* Define to 1 if you have timerfd support. */
#cmakedefine HAVE_TIMERFD 1
/* Define to 1 if you have the <signal.h> header file. */
#cmakedefine HAVE_SIGNAL_H 1
@ -53,6 +56,9 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the 'clock_gettime' function. */
#cmakedefine HAVE_CLOCK_GETTIME 1
/* Darwin backend */
#cmakedefine OS_DARWIN 1
@ -68,14 +74,11 @@
/* Windows backend */
#cmakedefine OS_WINDOWS 1
/* type of second poll() argument */
#define POLL_NFDS_TYPE @POLL_NFDS_TYPE@
/* Use POSIX Platform */
#cmakedefine PLATFORM_POSIX
/* Use POSIX Threads */
#cmakedefine THREADS_POSIX
/* timerfd headers available */
#cmakedefine USBI_TIMERFD_AVAILABLE 1
/* Use Windows Platform */
#cmakedefine PLATFORM_WINDOWS
/* Enable output to system log */
#define USE_SYSTEM_LOGGING_FACILITY 1

View File

@ -1,33 +1,6 @@
# Disable building the stuff we don't need.
set(SDL_DISKAUDIO OFF CACHE BOOL "")
set(SDL_OPENGL ON CACHE BOOL "")
set(SDL_OPENGLES ON CACHE BOOL "")
set(SDL_OSS OFF CACHE BOOL "")
set(SDL_ALSA OFF CACHE BOOL "")
set(SDL_JACK OFF CACHE BOOL "")
set(SDL_ESD OFF CACHE BOOL "")
set(SDL_PIPEWIRE OFF CACHE BOOL "")
set(SDL_PULSEAUDIO OFF CACHE BOOL "")
set(SDL_ARTS OFF CACHE BOOL "")
set(SDL_NAS OFF CACHE BOOL "")
set(SDL_SNDIO OFF CACHE BOOL "")
set(SDL_FUSIONSOUND OFF CACHE BOOL "")
set(SDL_LIBSAMPLERATE OFF CACHE BOOL "")
set(SDL_X11 OFF CACHE BOOL "")
set(SDL_WAYLAND OFF CACHE BOOL "")
set(SDL_RPI OFF CACHE BOOL "")
set(SDL_COCOA ON CACHE BOOL "")
set(SDL_DIRECTX OFF CACHE BOOL "")
set(SDL_WASAPI OFF CACHE BOOL "")
set(SDL_RENDER_D3D OFF CACHE BOOL "")
set(SDL_RENDER_METAL OFF CACHE BOOL "")
set(SDL_VIVANTE OFF CACHE BOOL "")
set(SDL_VULKAN OFF CACHE BOOL "")
set(SDL_METAL OFF CACHE BOOL "")
set(SDL_KMSDRM OFF CACHE BOOL "")
set(SDL_OFFSCREEN OFF CACHE BOOL "")
set(SDL_SHARED ON CACHE BOOL "")
set(SDL_STATIC OFF CACHE BOOL "")
# Configure static library build
set(SDL_SHARED OFF CACHE BOOL "")
set(SDL_STATIC ON CACHE BOOL "")
# Subsystems
set(SDL_ATOMIC ON CACHE BOOL "")
@ -43,7 +16,7 @@ set(SDL_THREADS ON CACHE BOOL "")
set(SDL_TIMERS ON CACHE BOOL "")
set(SDL_FILE ON CACHE BOOL "")
set(SDL_LOADSO ON CACHE BOOL "")
set(SDL_CPUINFO OFF CACHE BOOL "")
set(SDL_CPUINFO ON CACHE BOOL "")
set(SDL_FILESYSTEM OFF CACHE BOOL "")
set(SDL_DLOPEN ON CACHE BOOL "")
set(SDL_SENSOR OFF CACHE BOOL "")

1
externals/sirit vendored Submodule

Submodule externals/sirit added at 4ab79a8c02

1
externals/vma vendored Submodule

Submodule externals/vma added at 0e89587db3

1
externals/vulkan-headers vendored Submodule

2
externals/zstd vendored

View File

@ -40,7 +40,6 @@ if (MSVC)
/Zo
/permissive-
/EHsc
/std:c++latest
/utf-8
/volatile:iso
/Zc:externConstexpr
@ -85,7 +84,7 @@ if (MSVC)
# Since MSVC's debugging information is not very deterministic, so we have to disable it
# when using ccache or other caching tools
if (CITRA_USE_CCACHE OR CITRA_USE_PRECOMPILED_HEADERS)
# Precompiled headers are deleted if not using /Z7. See https://github.com/nanoant/CMakePCHCompiler/issues/21
# Precompiled headers are deleted if not using /Z7. See https://github.com/nanoant/CMakePCHCompiler/issues/21
add_compile_options(/Z7)
else()
add_compile_options(/Zi)
@ -102,17 +101,12 @@ else()
-Wno-attributes
)
if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
add_compile_options("-stdlib=libc++")
if (CITRA_WARNINGS_AS_ERRORS)
add_compile_options(-Werror)
endif()
# Set file offset size to 64 bits.
#
# On modern Unixes, this is typically already the case. The lone exception is
# glibc, which may default to 32 bits. glibc allows this to be configured
# by setting _FILE_OFFSET_BITS.
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
add_definitions(-D_FILE_OFFSET_BITS=64)
if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
add_compile_options("-stdlib=libc++")
endif()
if (MINGW)
@ -120,14 +114,16 @@ else()
if (COMPILE_WITH_DWARF)
add_compile_options("-gdwarf")
endif()
if (MINGW_STATIC_BUILD)
add_definitions(-DQT_STATICPLUGIN)
add_compile_options("-static")
endif()
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
# Set file offset size to 64 bits.
#
# On modern Unixes, this is typically already the case. The lone exception is
# glibc, which may default to 32 bits. glibc allows this to be configured
# by setting _FILE_OFFSET_BITS.
add_definitions(-D_FILE_OFFSET_BITS=64)
# GNU ar: Create thin archive files.
# Requires binutils-2.19 or later.
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcTP <TARGET> <LINK_FLAGS> <OBJECTS>")
@ -143,9 +139,12 @@ add_subdirectory(video_core)
add_subdirectory(audio_core)
add_subdirectory(network)
add_subdirectory(input_common)
add_subdirectory(tests)
if (ENABLE_SDL2)
if (ENABLE_TESTS)
add_subdirectory(tests)
endif()
if (ENABLE_SDL2 AND ENABLE_SDL2_FRONTEND)
add_subdirectory(citra)
endif()
@ -153,11 +152,13 @@ if (ENABLE_QT)
add_subdirectory(citra_qt)
endif()
if (ENABLE_DEDICATED_ROOM)
add_subdirectory(dedicated_room)
endif()
if (ANDROID)
add_subdirectory(android/app/src/main/jni)
target_include_directories(citra-android PRIVATE android/app/src/main)
else()
add_subdirectory(dedicated_room)
endif()
if (ENABLE_WEB_SERVICE)

View File

@ -1,169 +0,0 @@
apply plugin: 'com.android.application'
/**
* Use the number of seconds/10 since Jan 1 2016 as the versionCode.
* This lets us upload a new build at most every 10 seconds for the
* next 680 years.
*/
def autoVersion = (int) (((new Date().getTime() / 1000) - 1451606400) / 10)
def buildType
def abiFilter = "arm64-v8a" //, "x86"
android {
compileSdkVersion 32
ndkVersion "25.1.8937393"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
// This is important as it will run lint but not abort on error
// Lint has some overly obnoxious "errors" that should really be warnings
abortOnError false
//Uncomment disable lines for test builds...
//disable 'MissingTranslation'bin
//disable 'ExtraTranslation'
}
defaultConfig {
// TODO If this is ever modified, change application_id in strings.xml
applicationId "org.citra.citra_emu"
minSdkVersion 28
targetSdkVersion 31
versionCode autoVersion
versionName getVersion()
ndk.abiFilters abiFilter
}
signingConfigs {
//release {
// storeFile file('')
// storePassword System.getenv('ANDROID_KEYPASS')
// keyAlias = 'key0'
// keyPassword System.getenv('ANDROID_KEYPASS')
//}
}
applicationVariants.all { variant ->
buildType = variant.buildType.name // sets the current build type
}
// Define build types, which are orthogonal to product flavors.
buildTypes {
// Signed by release key, allowing for upload to Play Store.
release {
signingConfig signingConfigs.debug
}
// builds a release build that doesn't need signing
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
relWithDebInfo {
initWith release
applicationIdSuffix ".debug"
versionNameSuffix '-debug'
signingConfig signingConfigs.debug
minifyEnabled false
testCoverageEnabled false
debuggable true
jniDebuggable true
}
// Signed by debug key disallowing distribution on Play Store.
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
debug {
// TODO If this is ever modified, change application_id in debug/strings.xml
applicationIdSuffix ".debug"
versionNameSuffix '-debug'
debuggable true
jniDebuggable true
}
}
flavorDimensions "version"
productFlavors {
canary {
dimension "version"
applicationIdSuffix ".canary"
}
nightly {
dimension "version"
}
}
externalNativeBuild {
cmake {
version "3.22.1"
path "../../../CMakeLists.txt"
}
}
defaultConfig {
externalNativeBuild {
cmake {
arguments "-DENABLE_QT=0", // Don't use QT
"-DENABLE_SDL2=0", // Don't use SDL
"-DENABLE_WEB_SERVICE=0", // Don't use telemetry
"-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work
"-DBUNDLE_SPEEX=ON"
abiFilters abiFilter
}
}
}
}
dependencies {
implementation "androidx.activity:activity:1.5.1"
implementation "androidx.fragment:fragment:1.5.5"
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'androidx.exifinterface:exifinterface:1.3.4'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation "androidx.documentfile:documentfile:1.0.1"
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.5.1'
implementation 'androidx.fragment:fragment:1.5.3'
implementation "androidx.slidingpanelayout:slidingpanelayout:1.2.0"
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.core:core-splashscreen:1.0.0'
// For loading huge screenshots from the disk.
implementation 'com.squareup.picasso:picasso:2.71828'
// Allows FRP-style asynchronous operations in Android.
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'org.ini4j:ini4j:0.5.4'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
// Please don't upgrade the billing library as the newer version is not GPL-compatible
implementation 'com.android.billingclient:billing:2.0.3'
// To use the androidx.test.core APIs
androidTestImplementation "androidx.test:core:1.5.0"
androidTestImplementation "androidx.test.ext:junit:1.1.5"
}
def getVersion() {
def versionName = '0.0'
try {
versionName = 'git describe --always --long'.execute([], project.rootDir).text
.trim()
.replaceAll(/(-0)?-[^-]+$/, "")
} catch (Exception) {
logger.error('Cannot find git, defaulting to dummy version number')
}
if (System.getenv("GITHUB_ACTIONS") != null) {
def gitTag = System.getenv("GIT_TAG_NAME")
versionName = gitTag ?: versionName
}
return versionName
}

View File

@ -0,0 +1,203 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
import android.databinding.tool.ext.capitalizeUS
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
/**
* Use the number of seconds/10 since Jan 1 2016 as the versionCode.
* This lets us upload a new build at most every 10 seconds for the
* next 680 years.
*/
val autoVersion = (((System.currentTimeMillis() / 1000) - 1451606400) / 10).toInt()
val abiFilter = listOf("arm64-v8a"/*, "x86", "x86_64"*/)
@Suppress("UnstableApiUsage")
android {
namespace = "org.citra.citra_emu"
compileSdkVersion = "android-33"
ndkVersion = "25.2.9519653"
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
viewBinding = true
}
lint {
// This is important as it will run lint but not abort on error
// Lint has some overly obnoxious "errors" that should really be warnings
abortOnError = false
}
defaultConfig {
// TODO If this is ever modified, change application_id in strings.xml
applicationId = "org.citra.citra_emu"
minSdk = 28
targetSdk = 33
versionCode = autoVersion
versionName = getGitVersion()
ndk {
//noinspection ChromeOsAbiSupport
abiFilters += abiFilter
}
externalNativeBuild {
cmake {
arguments(
"-DENABLE_QT=0", // Don't use QT
"-DENABLE_SDL2=0", // Don't use SDL
"-DANDROID_ARM_NEON=true" // cryptopp requires Neon to work
)
}
}
}
val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE")
if (keystoreFile != null) {
signingConfigs {
create("release") {
storeFile = file(keystoreFile)
storePassword = System.getenv("ANDROID_KEYSTORE_PASS")
keyAlias = System.getenv("ANDROID_KEY_ALIAS")
keyPassword = System.getenv("ANDROID_KEYSTORE_PASS")
}
}
}
// Define build types, which are orthogonal to product flavors.
buildTypes {
// Signed by release key, allowing for upload to Play Store.
release {
signingConfig = if (keystoreFile != null) {
signingConfigs.getByName("release")
} else {
signingConfigs.getByName("debug")
}
}
// builds a release build that doesn't need signing
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
register("relWithDebInfo") {
initWith(getByName("release"))
applicationIdSuffix = ".debug"
versionNameSuffix = "-debug"
signingConfig = signingConfigs.getByName("debug")
isMinifyEnabled = false
isDebuggable = true
isJniDebuggable = true
}
// Signed by debug key disallowing distribution on Play Store.
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
debug {
// TODO If this is ever modified, change application_id in debug/strings.xml
applicationIdSuffix = ".debug"
versionNameSuffix = "-debug"
isDebuggable = true
isJniDebuggable = true
}
}
flavorDimensions.add("version")
productFlavors {
create("canary") {
dimension = "version"
applicationIdSuffix = ".canary"
}
create("nightly") {
dimension = "version"
}
}
externalNativeBuild {
cmake {
version = "3.22.1"
path = file("../../../CMakeLists.txt")
}
}
}
dependencies {
implementation("androidx.activity:activity-ktx:1.7.2")
implementation("androidx.fragment:fragment-ktx:1.6.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.documentfile:documentfile:1.0.1")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
implementation("androidx.slidingpanelayout:slidingpanelayout:1.2.0")
implementation("com.google.android.material:material:1.9.0")
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("androidx.work:work-runtime:2.8.1")
// For loading huge screenshots from the disk.
implementation("com.squareup.picasso:picasso:2.71828")
// Allows FRP-style asynchronous operations in Android.
implementation("io.reactivex:rxandroid:1.2.1")
implementation("org.ini4j:ini4j:0.5.4")
implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
// Please don't upgrade the billing library as the newer version is not GPL-compatible
implementation("com.android.billingclient:billing:2.0.3")
}
fun getGitVersion(): String {
var versionName = "0.0"
try {
versionName = ProcessBuilder("git", "describe", "--always", "--long")
.directory(project.rootDir)
.redirectOutput(ProcessBuilder.Redirect.PIPE)
.redirectError(ProcessBuilder.Redirect.PIPE)
.start().inputStream.bufferedReader().use { it.readText() }
.trim()
.replace(Regex("(-0)?-[^-]+$"), "")
} catch (e: Exception) {
logger.error("Cannot find git, defaulting to dummy version number")
}
if (System.getenv("GITHUB_ACTIONS") != null) {
val gitTag = System.getenv("GIT_TAG_NAME")
versionName = gitTag ?: versionName
}
return versionName
}
android.applicationVariants.configureEach {
val variant = this
val capitalizedName = variant.name.capitalizeUS()
val copyTask = tasks.register("copyBundle${capitalizedName}") {
doLast {
project.copy {
from(variant.outputs.first().outputFile.parentFile)
include("*.apk")
into(layout.buildDirectory.dir("bundle"))
}
project.copy {
from(layout.buildDirectory.dir("outputs/bundle/${variant.name}"))
include("*.aab")
into(layout.buildDirectory.dir("bundle"))
}
}
}
tasks.named("bundle${capitalizedName}").configure { finalizedBy(copyTask) }
}

View File

@ -1,26 +0,0 @@
package org.citra.citra_emu;
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = ApplicationProvider.getApplicationContext();
assertEquals("org.citra.citra_emu", appContext.getPackageName());
}
}

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.citra.citra_emu">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false"/>
@ -30,6 +29,7 @@
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:name="org.citra.citra_emu.CitraApplication"

View File

@ -23,16 +23,33 @@ public class CitraApplication extends Application {
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
NotificationManager notificationManager = getSystemService(NotificationManager.class);
{
// General notification
CharSequence name = getString(R.string.app_notification_channel_name);
String description = getString(R.string.app_notification_channel_description);
NotificationChannel channel = new NotificationChannel(getString(R.string.app_notification_channel_id), name, NotificationManager.IMPORTANCE_LOW);
NotificationChannel channel = new NotificationChannel(
getString(R.string.app_notification_channel_id), name,
NotificationManager.IMPORTANCE_LOW);
channel.setDescription(description);
channel.setSound(null, null);
channel.setVibrationPattern(null);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
{
// CIA Install notifications
NotificationChannel channel = new NotificationChannel(
getString(R.string.cia_install_notification_channel_id),
getString(R.string.cia_install_notification_channel_name),
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(getString(R.string.cia_install_notification_channel_description));
channel.setSound(null, null);
channel.setVibrationPattern(null);
notificationManager.createNotificationChannel(channel);
}
}

View File

@ -128,29 +128,7 @@ public final class NativeLibrary {
public static native void InitGameIni(String gameID);
/**
* Gets the embedded icon within the given ROM.
*
* @param filename the file path to the ROM.
* @return an integer array containing the color data for the icon.
*/
public static native int[] GetIcon(String filename);
/**
* Gets the embedded title of the given ISO/ROM.
*
* @param filename The file path to the ISO/ROM.
* @return the embedded title of the ISO/ROM.
*/
public static native String GetTitle(String filename);
public static native String GetDescription(String filename);
public static native String GetGameId(String filename);
public static native String GetRegions(String filename);
public static native String GetCompany(String filename);
public static native long GetTitleId(String filename);
public static native String GetGitRevision();
@ -210,6 +188,11 @@ public final class NativeLibrary {
*/
public static native boolean IsRunning();
/**
* Returns the title ID of the currently running title, or 0 on failure.
*/
public static native long GetRunningTitleId();
/**
* Returns the performance stats for the current game
**/
@ -602,12 +585,10 @@ public final class NativeLibrary {
/// Notifies that the activity is now in foreground and camera devices can now be reloaded
public static native void ReloadCameraDevices();
public static native boolean LoadAmiibo(byte[] bytes);
public static native boolean LoadAmiibo(String path);
public static native void RemoveAmiibo();
public static native void InstallCIAS(String[] path);
public static final int SAVESTATE_SLOT_COUNT = 10;
public static final class SavestateInfo {

View File

@ -491,7 +491,7 @@ public final class EmulationActivity extends AppCompatActivity {
break;
case MENU_ACTION_OPEN_CHEATS:
CheatsActivity.launch(this);
CheatsActivity.launch(this, NativeLibrary.GetRunningTitleId());
break;
case MENU_ACTION_CLOSE_GAME:
@ -570,15 +570,7 @@ public final class EmulationActivity extends AppCompatActivity {
}
private void onAmiiboSelected(String selectedFile) {
boolean success = false;
try {
Uri uri = Uri.parse(selectedFile);
DocumentFile file = DocumentFile.fromSingleUri(this, uri);
byte[] bytes = FileUtil.getBytesFromFile(this, file);
success = NativeLibrary.LoadAmiibo(bytes);
} catch (IOException e) {
e.printStackTrace();
}
boolean success = NativeLibrary.LoadAmiibo(selectedFile);
if (!success) {
new MaterialAlertDialogBuilder(this)

View File

@ -1,5 +1,6 @@
package org.citra.citra_emu.adapters;
import android.content.Context;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.os.Build;
@ -14,10 +15,13 @@ import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.color.MaterialColors;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.citra.citra_emu.CitraApplication;
import org.citra.citra_emu.NativeLibrary;
import org.citra.citra_emu.R;
import org.citra.citra_emu.activities.EmulationActivity;
import org.citra.citra_emu.features.cheats.ui.CheatsActivity;
import org.citra.citra_emu.model.GameDatabase;
import org.citra.citra_emu.utils.FileUtil;
import org.citra.citra_emu.utils.Log;
@ -31,8 +35,7 @@ import java.util.stream.Stream;
* ContentProviders and Loaders, allows for efficient display of a limited view into a (possibly)
* large dataset.
*/
public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
View.OnClickListener {
public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> {
private Cursor mCursor;
private GameDataSetObserver mObserver;
@ -61,7 +64,8 @@ public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> impl
View gameCard = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_game, parent, false);
gameCard.setOnClickListener(this);
gameCard.setOnClickListener(this::onClick);
gameCard.setOnLongClickListener(this::onLongClick);
// Use that view to create a ViewHolder.
return new GameViewHolder(gameCard);
@ -193,10 +197,9 @@ public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> impl
/**
* Launches the game that was clicked on.
*
* @param view The card representing the game the user wants to play.
* @param view The view representing the game the user wants to play.
*/
@Override
public void onClick(View view) {
private void onClick(View view) {
// Double-click prevention, using threshold of 1000 ms
if (SystemClock.elapsedRealtime() - mLastClickTime < 1000) {
return;
@ -208,6 +211,31 @@ public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> impl
EmulationActivity.launch((FragmentActivity) view.getContext(), holder.path, holder.title);
}
/**
* Opens the cheats settings for the game that was clicked on.
*
* @param view The view representing the game the user wants to play.
*/
private boolean onLongClick(View view) {
Context context = view.getContext();
GameViewHolder holder = (GameViewHolder) view.getTag();
final long titleId = NativeLibrary.GetTitleId(holder.path);
if (titleId == 0) {
new MaterialAlertDialogBuilder(context)
.setIcon(R.mipmap.ic_launcher)
.setTitle(R.string.properties)
.setMessage(R.string.properties_not_loaded)
.setPositiveButton(android.R.string.ok, null)
.show();
} else {
CheatsActivity.launch(context, titleId);
}
return true;
}
private boolean isValidGame(String path) {
return Stream.of(
".rar", ".zip", ".7z", ".torrent", ".tar", ".gz").noneMatch(suffix -> path.toLowerCase().endsWith(suffix));

View File

@ -1,13 +1,28 @@
package org.citra.citra_emu.features.cheats.model;
import androidx.annotation.Keep;
public class CheatEngine {
public static native Cheat[] getCheats();
@Keep
private final long mPointer;
public static native void addCheat(Cheat cheat);
@Keep
public CheatEngine(long titleId) {
mPointer = initialize(titleId);
}
public static native void removeCheat(int index);
private static native long initialize(long titleId);
public static native void updateCheat(int index, Cheat newCheat);
@Override
protected native void finalize();
public static native void saveCheatFile();
public native Cheat[] getCheats();
public native void addCheat(Cheat cheat);
public native void removeCheat(int index);
public native void updateCheat(int index, Cheat newCheat);
public native void saveCheatFile();
}

View File

@ -19,11 +19,17 @@ public class CheatsViewModel extends ViewModel {
private final MutableLiveData<Integer> mCheatDeletedEvent = new MutableLiveData<>(null);
private final MutableLiveData<Boolean> mOpenDetailsViewEvent = new MutableLiveData<>(false);
private CheatEngine mCheatEngine;
private Cheat[] mCheats;
private boolean mCheatsNeedSaving = false;
public void load() {
mCheats = CheatEngine.getCheats();
public void initialize(long titleId) {
mCheatEngine = new CheatEngine(titleId);
load();
}
private void load() {
mCheats = mCheatEngine.getCheats();
for (int i = 0; i < mCheats.length; i++) {
int position = i;
@ -36,7 +42,7 @@ public class CheatsViewModel extends ViewModel {
public void saveIfNeeded() {
if (mCheatsNeedSaving) {
CheatEngine.saveCheatFile();
mCheatEngine.saveCheatFile();
mCheatsNeedSaving = false;
}
}
@ -106,7 +112,7 @@ public class CheatsViewModel extends ViewModel {
int position = mCheats.length;
CheatEngine.addCheat(cheat);
mCheatEngine.addCheat(cheat);
mCheatsNeedSaving = true;
load();
@ -132,7 +138,7 @@ public class CheatsViewModel extends ViewModel {
}
public void updateSelectedCheat(Cheat newCheat) {
CheatEngine.updateCheat(mSelectedCheatPosition, newCheat);
mCheatEngine.updateCheat(mSelectedCheatPosition, newCheat);
mCheatsNeedSaving = true;
load();
@ -162,7 +168,7 @@ public class CheatsViewModel extends ViewModel {
setSelectedCheat(null, -1);
CheatEngine.removeCheat(position);
mCheatEngine.removeCheat(position);
mCheatsNeedSaving = true;
load();

View File

@ -32,6 +32,8 @@ import java.util.List;
public class CheatsActivity extends AppCompatActivity
implements SlidingPaneLayout.PanelSlideListener {
private static String ARG_TITLE_ID = "title_id";
private CheatsViewModel mViewModel;
private SlidingPaneLayout mSlidingPaneLayout;
@ -41,8 +43,9 @@ public class CheatsActivity extends AppCompatActivity
private View mCheatListLastFocus;
private View mCheatDetailsLastFocus;
public static void launch(Context context) {
public static void launch(Context context, long titleId) {
Intent intent = new Intent(context, CheatsActivity.class);
intent.putExtra(ARG_TITLE_ID, titleId);
context.startActivity(intent);
}
@ -54,8 +57,10 @@ public class CheatsActivity extends AppCompatActivity
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
long titleId = getIntent().getLongExtra(ARG_TITLE_ID, -1);
mViewModel = new ViewModelProvider(this).get(CheatsViewModel.class);
mViewModel.load();
mViewModel.initialize(titleId);
setContentView(R.layout.activity_cheats);

View File

@ -196,8 +196,12 @@ public final class SettingsFragmentPresenter {
sl.add(new SingleChoiceSetting(SettingsFile.KEY_REGION_VALUE, Settings.SECTION_SYSTEM, R.string.emulated_region, 0, R.array.regionNames, R.array.regionValues, -1, region));
sl.add(new SingleChoiceSetting(SettingsFile.KEY_LANGUAGE, Settings.SECTION_SYSTEM, R.string.emulated_language, 0, R.array.languageNames, R.array.languageValues, 1, language));
sl.add(new HeaderSetting(null, null, R.string.clock, 0));
sl.add(new SingleChoiceSetting(SettingsFile.KEY_INIT_CLOCK, Settings.SECTION_SYSTEM, R.string.init_clock, R.string.init_clock_description, R.array.systemClockNames, R.array.systemClockValues, 0, systemClock));
sl.add(new DateTimeSetting(SettingsFile.KEY_INIT_TIME, Settings.SECTION_SYSTEM, R.string.init_time, R.string.init_time_description, "2000-01-01 00:00:01", dateTime));
sl.add(new HeaderSetting(null, null, R.string.plugin_loader, 0));
sl.add(new CheckBoxSetting(SettingsFile.KEY_PLUGIN_LOADER, Settings.SECTION_SYSTEM, R.string.plugin_loader, R.string.plugin_loader_description, false, pluginLoader));
sl.add(new CheckBoxSetting(SettingsFile.KEY_ALLOW_PLUGIN_LOADER, Settings.SECTION_SYSTEM, R.string.allow_plugin_loader, R.string.allow_plugin_loader_description, true, allowPluginLoader));
}

View File

@ -12,6 +12,7 @@ import org.citra.citra_emu.utils.FileUtil;
import org.citra.citra_emu.utils.Log;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashSet;
@ -206,27 +207,26 @@ public final class GameDatabase extends SQLiteOpenHelper {
}
private static void attemptToAddGame(SQLiteDatabase database, String filePath) {
String name = NativeLibrary.GetTitle(filePath);
GameInfo gameInfo;
try {
gameInfo = new GameInfo(filePath);
} catch (IOException e) {
gameInfo = null;
}
String name = gameInfo != null ? gameInfo.getTitle() : "";
// If the game's title field is empty, use the filename.
if (name.isEmpty()) {
name = filePath.substring(filePath.lastIndexOf("/") + 1);
}
String gameId = NativeLibrary.GetGameId(filePath);
// If the game's ID field is empty, use the filename without extension.
if (gameId.isEmpty()) {
gameId = filePath.substring(filePath.lastIndexOf("/") + 1,
filePath.lastIndexOf("."));
}
ContentValues game = Game.asContentValues(name,
NativeLibrary.GetDescription(filePath).replace("\n", " "),
NativeLibrary.GetRegions(filePath),
filePath.replace("\n", " "),
gameInfo != null ? gameInfo.getRegions() : "Invalid region",
filePath,
gameId,
NativeLibrary.GetCompany(filePath));
filePath,
gameInfo != null ? gameInfo.getCompany() : "");
// Try to update an existing game first.
int rowsMatched = database.update(TABLE_NAME_GAMES, // Which table to update.

View File

@ -0,0 +1,37 @@
package org.citra.citra_emu.model;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.IOException;
public class GameInfo {
@Keep
private final long mPointer;
@Keep
public GameInfo(String path) throws IOException {
mPointer = initialize(path);
if (mPointer == 0L) {
throw new IOException();
}
}
private static native long initialize(String path);
@Override
protected native void finalize();
@NonNull
public native String getTitle();
@NonNull
public native String getRegions();
@NonNull
public native String getCompany();
@Nullable
public native int[] getIcon();
}

View File

@ -1,7 +1,10 @@
package org.citra.citra_emu.ui.main;
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.view.Menu;
import android.view.MenuInflater;
@ -13,6 +16,7 @@ import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.core.splashscreen.SplashScreen;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.Collections;
@ -20,10 +24,15 @@ import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.work.Data;
import androidx.work.ExistingWorkPolicy;
import androidx.work.OneTimeWorkRequest;
import androidx.work.OutOfQuotaPolicy;
import androidx.work.WorkManager;
import androidx.work.WorkRequest;
import com.google.android.material.appbar.AppBarLayout;
import org.citra.citra_emu.NativeLibrary;
import org.citra.citra_emu.R;
import org.citra.citra_emu.activities.EmulationActivity;
import org.citra.citra_emu.contracts.OpenFileResultContract;
@ -32,6 +41,7 @@ import org.citra.citra_emu.model.GameProvider;
import org.citra.citra_emu.ui.platform.PlatformGamesFragment;
import org.citra.citra_emu.utils.AddDirectoryHelper;
import org.citra.citra_emu.utils.BillingManager;
import org.citra.citra_emu.utils.CiaInstallWorker;
import org.citra.citra_emu.utils.CitraDirectoryHelper;
import org.citra.citra_emu.utils.DirectoryInitialization;
import org.citra.citra_emu.utils.FileBrowserHelper;
@ -50,7 +60,9 @@ public final class MainActivity extends AppCompatActivity implements MainView {
private int mFrameLayoutId;
private PlatformGamesFragment mPlatformGamesFragment;
private MainPresenter mPresenter = new MainPresenter(this);
private final MainPresenter mPresenter = new MainPresenter(this);
// private final CiaInstallWorker mCiaInstallWorker = new CiaInstallWorker();
// Singleton to manage user billing state
private static BillingManager mBillingManager;
@ -91,7 +103,7 @@ public final class MainActivity extends AppCompatActivity implements MainView {
mPresenter.onDirectorySelected(result.toString());
});
private final ActivityResultLauncher<Boolean> mOpenFileLauncher =
private final ActivityResultLauncher<Boolean> mInstallCiaFileLauncher =
registerForActivityResult(new OpenFileResultContract(), result -> {
if (result == null)
return;
@ -104,10 +116,21 @@ public final class MainActivity extends AppCompatActivity implements MainView {
.show();
return;
}
NativeLibrary.InstallCIAS(selectedFiles);
mPresenter.refreshGameList();
WorkManager workManager = WorkManager.getInstance(getApplicationContext());
workManager.enqueueUniqueWork("installCiaWork", ExistingWorkPolicy.APPEND_OR_REPLACE,
new OneTimeWorkRequest.Builder(CiaInstallWorker.class)
.setInputData(
new Data.Builder().putStringArray("CIA_FILES", selectedFiles)
.build()
)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
);
});
private final ActivityResultLauncher<String> requestNotificationPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { });
@Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen splashScreen = SplashScreen.installSplashScreen(this);
@ -149,6 +172,12 @@ public final class MainActivity extends AppCompatActivity implements MainView {
EmulationActivity.tryDismissRunningNotification(this);
setInsets();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
requestNotificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS);
}
}
}
@Override
@ -233,7 +262,7 @@ public final class MainActivity extends AppCompatActivity implements MainView {
mOpenGameListLauncher.launch(null);
break;
case MainPresenter.REQUEST_INSTALL_CIA:
mOpenFileLauncher.launch(true);
mInstallCiaFileLauncher.launch(true);
break;
}
} else {

View File

@ -0,0 +1,160 @@
package org.citra.citra_emu.utils;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import androidx.work.ForegroundInfo;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import org.citra.citra_emu.R;
public class CiaInstallWorker extends Worker {
private final Context mContext = getApplicationContext();
private final NotificationManager mNotificationManager =
mContext.getSystemService(NotificationManager.class);
static final String GROUP_KEY_CIA_INSTALL_STATUS = "org.citra.citra_emu.CIA_INSTALL_STATUS";
private final NotificationCompat.Builder mInstallProgressBuilder = new NotificationCompat.Builder(
mContext, mContext.getString(R.string.cia_install_notification_channel_id))
.setContentTitle(mContext.getString(R.string.install_cia_title))
.setContentIntent(PendingIntent.getBroadcast(mContext, 0,
new Intent("CitraDoNothing"), PendingIntent.FLAG_IMMUTABLE))
.setSmallIcon(R.drawable.ic_stat_notification_logo);
private final NotificationCompat.Builder mInstallStatusBuilder = new NotificationCompat.Builder(
mContext, mContext.getString(R.string.cia_install_notification_channel_id))
.setContentTitle(mContext.getString(R.string.install_cia_title))
.setSmallIcon(R.drawable.ic_stat_notification_logo)
.setGroup(GROUP_KEY_CIA_INSTALL_STATUS);
private final Notification mSummaryNotification =
new NotificationCompat.Builder(mContext, mContext.getString(R.string.cia_install_notification_channel_id))
.setContentTitle(mContext.getString(R.string.install_cia_title))
.setSmallIcon(R.drawable.ic_stat_notification_logo)
.setGroup(GROUP_KEY_CIA_INSTALL_STATUS)
.setGroupSummary(true)
.build();
private static long mLastNotifiedTime = 0;
private static final int SUMMARY_NOTIFICATION_ID = 0xC1A0000;
private static final int PROGRESS_NOTIFICATION_ID = SUMMARY_NOTIFICATION_ID + 1;
private static int mStatusNotificationId = SUMMARY_NOTIFICATION_ID + 2;
public CiaInstallWorker(
@NonNull Context context,
@NonNull WorkerParameters params) {
super(context, params);
}
enum InstallStatus {
Success,
ErrorFailedToOpenFile,
ErrorFileNotFound,
ErrorAborted,
ErrorInvalid,
ErrorEncrypted,
}
private void notifyInstallStatus(String filename, InstallStatus status) {
switch(status){
case Success:
mInstallStatusBuilder.setContentTitle(
mContext.getString(R.string.cia_install_notification_success_title));
mInstallStatusBuilder.setContentText(
mContext.getString(R.string.cia_install_success, filename));
break;
case ErrorAborted:
mInstallStatusBuilder.setContentTitle(
mContext.getString(R.string.cia_install_notification_error_title));
mInstallStatusBuilder.setStyle(new NotificationCompat.BigTextStyle()
.bigText(mContext.getString(
R.string.cia_install_error_aborted, filename)));
break;
case ErrorInvalid:
mInstallStatusBuilder.setContentTitle(
mContext.getString(R.string.cia_install_notification_error_title));
mInstallStatusBuilder.setContentText(
mContext.getString(R.string.cia_install_error_invalid, filename));
break;
case ErrorEncrypted:
mInstallStatusBuilder.setContentTitle(
mContext.getString(R.string.cia_install_notification_error_title));
mInstallStatusBuilder.setStyle(new NotificationCompat.BigTextStyle()
.bigText(mContext.getString(
R.string.cia_install_error_encrypted, filename)));
break;
case ErrorFailedToOpenFile:
// TODO:
case ErrorFileNotFound:
// shouldn't happen
default:
mInstallStatusBuilder.setContentTitle(
mContext.getString(R.string.cia_install_notification_error_title));
mInstallStatusBuilder.setStyle(new NotificationCompat.BigTextStyle()
.bigText(mContext.getString(R.string.cia_install_error_unknown, filename)));
break;
}
// Even if newer versions of Android don't show the group summary text that you design,
// you always need to manually set a summary to enable grouped notifications.
mNotificationManager.notify(SUMMARY_NOTIFICATION_ID, mSummaryNotification);
mNotificationManager.notify(mStatusNotificationId++, mInstallStatusBuilder.build());
}
@NonNull
@Override
public Result doWork() {
String[] selectedFiles = getInputData().getStringArray("CIA_FILES");
assert selectedFiles != null;
final CharSequence toastText = mContext.getResources().getQuantityString(R.plurals.cia_install_toast,
selectedFiles.length, selectedFiles.length);
getApplicationContext().getMainExecutor().execute(() -> Toast.makeText(mContext, toastText,
Toast.LENGTH_LONG).show());
// Issue the initial notification with zero progress
mInstallProgressBuilder.setOngoing(true);
setProgressCallback(100, 0);
int i = 0;
for (String file : selectedFiles) {
String filename = FileUtil.getFilename(mContext, file);
mInstallProgressBuilder.setContentText(mContext.getString(
R.string.cia_install_notification_installing, filename, ++i, selectedFiles.length));
InstallStatus res = InstallCIA(file);
notifyInstallStatus(filename, res);
}
mNotificationManager.cancel(PROGRESS_NOTIFICATION_ID);
return Result.success();
}
public void setProgressCallback(int max, int progress) {
long currentTime = System.currentTimeMillis();
// Android applies a rate limit when updating a notification.
// If you post updates to a single notification too frequently,
// such as many in less than one second, the system might drop updates.
// TODO: consider moving to C++ side
if (currentTime - mLastNotifiedTime < 500 /* ms */){
return;
}
mLastNotifiedTime = currentTime;
mInstallProgressBuilder.setProgress(max, progress, false);
mNotificationManager.notify(PROGRESS_NOTIFICATION_ID, mInstallProgressBuilder.build());
}
@NonNull
@Override
public ForegroundInfo getForegroundInfo() {
return new ForegroundInfo(PROGRESS_NOTIFICATION_ID, mInstallProgressBuilder.build());
}
private native InstallStatus InstallCIA(String path);
}

Some files were not shown because too many files have changed in this diff Show More