894 Commits
Author SHA1 Message Date
Flyinghead 5eadfb388e dreampotato: change timeout values. disconnect on receive error
initial RTT timeout is 500 ms then 100 ms
2026-01-16 13:12:03 +01:00
Flyinghead 83f6d818b5 maplelink: disable savestates. Change some options default. Bug fix
Disable load/save state if at least one MapleLink with storage enabled.
Change UsePhysicalMemory default to false.
Change Per Game VMU A1 default to true.
Fix DreamLink infinite loop on exit.
dreampotato, dreamconn: don't use stringstream for output
dreampotato: libretro support (no VMU storage yet)
2026-01-16 13:08:54 +01:00
Flyinghead bbae3de9a4 switch: build fix 2026-01-15 17:23:08 +01:00
Flyinghead c2f66018d8 lr: build fix 2026-01-15 16:17:00 +01:00
Flyinghead 82ca2db61a !win32 build fix 2026-01-15 16:01:26 +01:00
Flyinghead b4d83c0d12 DreamLink refactoring
Introduce MapleLink base interface and DreamPotato implementation.
2026-01-15 15:45:14 +01:00
Stefan Schlosser 1aba1b467e deps: prevent installing DreamPicoPort artifacts
Currently the install-target of the DreamPicoPort-API dependency is
executed when installing flycast. This results in the include file
DreamPicoPortApi.hpp and the static library libdream_pico_port_api.a to
be installed alongside flycast.

Add EXCLUDE_FROM_ALL to add_subdirectory to prevent this.
2026-01-14 12:17:21 +01:00
Flyinghead 5be5eeb905 naomi: more rom crc32
[ci skip]
2026-01-14 12:17:02 +01:00
Flyinghead 2f842238a5 ini: don't save transient values and empty sections 2026-01-14 12:16:23 +01:00
flyinghead 3de74672ce Crowdin Translations: Japanese, Swedish 2026-01-13 11:41:42 +01:00
Flyinghead b76b1c7275 Merge remote-tracking branch 'origin/master' into dev
[ci skip]
2026-01-13 11:39:33 +01:00
Flyinghead 392a429e8b boxart: replace invalid utf-8 chars instead of failing when saving
Open (and truncate) the file only after json serialization.
2026-01-07 14:28:32 +01:00
Flyinghead 0491f2e6a5 reios: check boot file destination ptr before loading
Abort load if ptr is null (size > 0xff0000)
Fixes MINIDUMP-7W9 MINIDUMP-84B MINIDUMP-87V
2026-01-07 09:50:35 +01:00
Flyinghead 33d9a58cf9 emu: don't crash if unexpected state in Emulator::start()
Simply log and ignore. Happens on android under some undetermined
conditions.
Fixes MINIDUMP-2Q MINIDUMP-3SG
2026-01-07 08:52:36 +01:00
Flyinghead 401332d520 sdl: don't run haptic sine effect if rumblePower is 0 2026-01-06 16:23:47 +01:00
Flyinghead 8511d1ad3c dreamconn: only build on win32. remove unused code 2026-01-06 16:21:35 +01:00
Flyinghead 7ce50e5229 mmu: stricter test before enabling on-demand MMU
Visual Concepts games and many naomi and systemsp games create some
bogus mappings at boot. Ignore those

Issue #2184
2026-01-05 11:48:03 +01:00
Flyinghead 99fc194dd0 ini: transient values always hide regular ones regardless of order 2026-01-05 11:42:41 +01:00
Craig d794b53512 webOS: disable OPENMP as not available until webOS 3.9.2 (#2188)
[ci skip]
2026-01-04 21:10:03 +01:00
vkedwardli bd8f7c8a75 Update imgui to v1.92.5 (#2180)
Update ImGui from v1.92.1 to v1.92.5
2026-01-04 10:56:36 +01:00
Craig 594d82b223 add webOS to CMakeLists (#2167)
[ci skip]
2026-01-04 10:55:23 +01:00
Flyinghead fd72eebbe3 mmu: enable full MMU when non-SQ mapping is created
Fixes super mario 64 audio
Issue #2184
[ci skip]
2026-01-04 10:53:12 +01:00
Flyinghead fea8699884 modem: enforce correct tx speed for dissymmetric connections 2026-01-04 10:48:01 +01:00
Flyinghead d00b5d4c17 modem: 56K support, V8 bis protocol 2026-01-03 17:52:43 +01:00
Flyinghead 74cbee908f arm64 rec: proper fix for MINIDUMP-7W0
ModeImmediateHelper can generate code, resulting in the Mov op being
generated twice.
Fixes MINIDUMP-7W0
2026-01-02 11:51:23 +01:00
flyinghead 1652143f5f New translations flycast.pot (Hungarian)
New translations for {languageName}
2025-12-31 18:25:10 +01:00
Flyinghead 4886dcb1c2 enable rtt2vram for Jikkyo Powerful Pro Yakyu
Issue #2182
2025-12-29 20:20:15 +01:00
flyinghead 75bca2a166 Crowdin Translations: Hungarian and Japanese 2025-12-28 17:51:30 +01:00
Flyinghead 13df86c520 modem: V42bis compression support
[ci skip]
2025-12-28 17:51:01 +01:00
Rikki Gibson 16fc172ffc DreamConn: fix compat issue involving slot 2 VMU support (#2172)
* Do not create a shared_ptr from destructor
* Fall back when MDC_DeviceRequest message does not have an expected response
* Assume the device type for physical DreamConn controllers
* DreamConn controllers do not support physical VMU memory
* Do not maple_ReconnectDevices for DreamConn controller
2025-12-27 19:40:13 +01:00
Flyinghead dfb2ae8987 android: touch mouse may be null so check before delivering events
Fixes MINIDUMP-6S6
[ci skip]
2025-12-27 19:36:51 +01:00
Flyinghead 4529a31372 don't save state when game filename is empty
Happens on android apparently due to issues with automatic savestate and
app pausing.
2025-12-27 19:35:30 +01:00
Flyinghead 5a29ac489f sdl: fix DreamPicoPort crash
io_context_thread can be null in the destructor.
Fixes MINIDUMP-83F
2025-12-27 19:31:32 +01:00
github-actions[bot] c4c3c2ae93 Fetch translations & Recreate libretro_core_options_intl.h 2025-12-26 22:21:56 +00:00
flyinghead 8a228e4e16 Crowdin Translations: Swedish 2025-12-24 17:25:38 +01:00
Flyinghead 0a3c68f7cc i18n: delete bogus zh_CH.po. Load correct one
[ci skip]
2025-12-24 17:25:01 +01:00
flyinghead 4905dc21c8 Crowdin Translations: Japanese 2025-12-23 15:30:29 +01:00
Flyinghead 98dfb4c32a modem: implement V14 sync-async mode and V42 protocol
Use modem sync mode when ASYN is reset.
Implement V14 sync-async mode for V42 detection. Also used by Power
Smash and Pro Yakyu Team de Asobou Net!
Switch to V42 protocol for most games.
Set correct modem speed and timing as set by the game.
Get rid of modem speed/automode cheats.
[ci skip]
2025-12-23 15:29:42 +01:00
Flyinghead df2bdfc9bf ui: support for Asian fonts on linux
Fix width of "Filter" field in the game list.
crowdin.yml: fix typo for zh_CN resource files.
2025-12-23 12:00:53 +01:00
flyinghead e86c1c992f Crowdin Translations: Japanese
courtesy of @kihato
2025-12-22 21:23:57 +01:00
Flyinghead 5b6cc33a75 i18n: add Japanese translation
[ci skip]
2025-12-22 21:22:27 +01:00
flyinghead e37518524f Crowdin Translations: Hungarian and Portuguese, Brazilian 2025-12-21 15:04:05 +01:00
Flyinghead 994f72f954 ci: upload symbols to sentry on push only
[ci skip]
2025-12-21 15:03:09 +01:00
Flyinghead 5978b3a058 ui: merge Asian glyphs into large font too
Issue #2169
2025-12-21 15:00:28 +01:00
flyinghead bb12d5c72d Crowdin Translations (#2162) Hungarian
courtesy of oldman63
2025-12-18 15:56:18 +01:00
Flyinghead b127c96cf3 i18n: Add hu.po to resources
[ci skip]
2025-12-18 15:54:19 +01:00
scribam 0d3beb1c6d fix misleading indentation warning 2025-12-17 14:00:11 +01:00
Flyinghead 9bd3179745 i18n: set all stringstreams to classic locale
Fixes dumped texture names being formatted with the thousands separator
of the current locale.
[ci skip]
2025-12-17 13:59:25 +01:00
Flyinghead 5833fb3a47 ui: use imgui touch support and get rid of delay touch hack 2025-12-16 17:20:45 +01:00
Flyinghead 49ec396e24 i18n: delete empty message files. add zh_HK.po 2025-12-16 17:20:45 +01:00
Stefan Schlosser 5607b8eebd libretro: freebsd build fix 2025-12-16 17:18:52 +01:00
scribam 35888406d3 ci: libretro android build fixes (#2156)
Followup to #2151
[ci skip]
2025-12-16 17:18:32 +01:00
scribam 6b3bbd6f85 ci: update actions (#2155)
* ci: update actions
* ci: use freebsd 15 and openbsd 7.8
[ci skip]
2025-12-16 17:18:07 +01:00
James Smith ef689fd35d Minor bug fixes for DreamPicoPort 2025-12-15 18:05:32 +01:00
scribam 6a78f27bef ci: libretro android build fixes (#2151)
[ci skip]
2025-12-15 18:05:11 +01:00
scribam 97de155fd8 ci: enable libretro on bsd systems (#2150)
[ci skip]
2025-12-15 18:01:47 +01:00
scribam f183f30262 dragonflybsd: build fixes (#2149)
[ci skip]
2025-12-15 18:01:08 +01:00
flyinghead 065c91f9ad Crowdin Translations (#2148)
[ci skip]
2025-12-15 18:00:22 +01:00
Edward Li f65907a256 Remove custom_texture.terminate() during TexCache.Clear() 2025-12-15 12:27:57 +01:00
scribam 161d057d4c haiku: build fixes 2025-12-14 14:47:24 +01:00
scribam a7ee2e9a66 libretro: netbsd/openbsd build fixes 2025-12-14 14:46:52 +01:00
flyinghead e08ec86962 Crowdin Translations (#2143)
[ci skip]
2025-12-14 14:46:29 +01:00
Flyinghead 7653b1c811 sh4: don't crash when FIPR is executed with PR=1
[ci skip]
2025-12-14 14:45:53 +01:00
Flyinghead 1475812a94 i18n: localize input devices names, buttons and axes 2025-12-14 14:35:09 +01:00
flyinghead c8a724ad63 Crowdin Translations (#2142)
French, Swedish
2025-12-13 17:25:16 +01:00
Flyinghead 2cfce747c5 ui: better egl init test. display message box on graphics init error
Fail if eglGetDisplay() is null.
Throw exception on initRenderApi/switchRenderApi failure.
Catch in SDL and Android and show error message.
Localize Android java code.

Fixes MINIDUMP-7SD MINIDUMP-2XH MINIDUMP-5KM MINIDUMP-2FF MINIDUMP-4ZP
MINIDUMP-6T1 MINIDUMP-5D3 MINIDUMP-7ME
[ci skip]
2025-12-13 17:23:55 +01:00
github-actions[bot] 37a9077304 Fetch translations & Recreate libretro_core_options_intl.h 2025-12-12 22:21:51 +00:00
Flyinghead f8bdf6c35e crowdin.yml: fix pt_BR typo
[ci skip]
2025-12-12 21:51:46 +01:00
Flyinghead f4c2d001bd crowdin.yml: add android resource
[ci skip]
2025-12-12 20:04:07 +01:00
Flyinghead f3ddec5f1e android: add localizable strings resource
[ci skip]
2025-12-12 19:53:04 +01:00
scribam 13c7ddc6c9 deps: remove core/deps/libusb-cmake 2025-12-12 19:39:50 +01:00
nexus382 c24d7fb0fe Send game id to vmu pro/vm2 (#2126)
[ci skip]
2025-12-12 19:39:28 +01:00
Flyinghead 3ebc79a5ce Merge remote-tracking branch 'origin/master' into dev [ci skip] 2025-12-12 19:32:09 +01:00
Flyinghead 27a913fc02 arm recs: ensure block linking size doesn't depend on mmu mode
Due to d0ec876936 the mmu enabled path may
be taken when the emu is pausing, so make sure block linking uses the
same number of ops in both branches.
Fixes MINIDUMP-82C MINIDUMP-7T2 MINIDUMP-7W0
2025-12-12 16:49:50 +01:00
Flyinghead 97442c0411 terminate game id at first null character
Fixes MINIDUMP-7YW MINIDUMP-800
2025-12-12 16:13:44 +01:00
Flyinghead 5b12f9ca68 boxart: catch-all handler for scraper thread
Fixes MINIDUMP-7YW
2025-12-12 16:07:22 +01:00
Flyinghead 6a298289a9 ice: guard against null icePipe
Fixes MINIDUMP-7ZF
2025-12-12 16:03:44 +01:00
Flyinghead 59ef8579d2 ui: disable imgui debug tools
Fixes MINIDUMP-7RF
2025-12-12 16:01:52 +01:00
Flyinghead 6989a0aa2c test: fneg on odd register in PR=1 mode
Issue #2139
2025-12-11 16:26:37 +01:00
Flyinghead bd24812d0c jvs: return value from RawDma is incorrect for MIE firmware upload
It didn't seem to bother anyone however
2025-12-11 16:25:03 +01:00
Flyinghead 15889616dd add zh_CH and zh_TW messages. delete outdated docs
Issue #1830
2025-12-11 15:15:43 +01:00
Flyinghead e60efed8b5 pvr: limit framebuffer height to 240 when interlacing is disabled
Fixes Confidential Mission PAL Echelon intro
Issue #2062
2025-12-11 15:11:24 +01:00
Flyinghead 11fcadf37e sh4: fneg doesn't depend on FPSCR.PR at all
When PR=1, fneg can also be used on odd registers.
Issue #2139
2025-12-11 15:03:16 +01:00
Flyinghead 88b8a0b51e crowdin.yml: add zh_HK mapping [ci skip] 2025-12-10 17:15:24 +01:00
flyinghead 8e9a0f9c1f Crowdin Translations (#2136) pt_BR
New translations flycast.pot (Portuguese, Brazilian)
2025-12-10 11:42:58 +01:00
Flyinghead dd50fcf81c i18n: include pt_BR.po [ci skip] 2025-12-10 11:41:30 +01:00
Flyinghead 7b8656b944 imgread: more checks when loading GDI and CUE files (fail fast)
Add missing CMakeLists.txt change for new cue and gdi tests
2025-12-10 11:40:41 +01:00
Flyinghead 00ae6c42a2 fix some include paths 2025-12-09 19:41:48 +01:00
Flyinghead 8c4c463c38 add cue and gdi parsing tests. add non-C locale tests
delete old en resource file
libretro doesn't need cfg/ini.cpp/h anymore
2025-12-09 17:31:31 +01:00
Flyinghead 14f759eeb7 ice: fix crash when loading a state without being connected 2025-12-09 14:36:53 +01:00
flyinghead 329b6a1e34 Crowdin Translations (#2134)
New translations: sv, pt, pt_BR
2025-12-09 09:23:08 +01:00
Flyinghead 9c28800384 i18n: std::from/to_chars missing on BSD and macOS
Use stringstream instead

[ci skip]
2025-12-09 09:21:54 +01:00
Flyinghead 602982fb56 add pt_BR crowdin mapping [ci skip] 2025-12-08 23:38:12 +01:00
flyinghead cb830e0bd3 Update Crowdin configuration file 2025-12-08 23:35:08 +01:00
Flyinghead ec3d85a96c remove [ci skip] in crowdin commit messages 2025-12-08 23:26:58 +01:00
Flyinghead d3bc72b0d0 ci: ignore push on l10n_* branches 2025-12-08 22:28:30 +01:00
Flyinghead 4170e783b9 fix GDI and CUE parsing error in non-English locale
IniFile: use locale-independant float conversions functions
Use std::ostringstream and std::istringstream as appropriate.
Use C locale for GDI and CUE parsing.
2025-12-08 22:26:33 +01:00
flyinghead 083ccb984a Crowdin Translations (#2133)
* New translations flycast.pot (French)
New translations for {languageName} [ci skip]
* New translations flycast.pot (Swedish)
New translations for {languageName} [ci skip]
2025-12-08 21:19:31 +01:00
Flyinghead 0220207545 strprintf utility. localize exception messages. add sv.po (Swedish) 2025-12-08 16:22:26 +01:00
flyinghead aee4cd34fc Crowdin Translations (#2132)
* New translations flycast.pot (French)
New translations for {languageName} [ci skip]
* New translations flycast.pot (Swedish)
New translations for {languageName} [ci skip]
* New translations flycast.pot (English, United Kingdom)
New translations for {languageName} [ci skip]
2025-12-08 16:15:17 +01:00
flyinghead a99cce27bb Crowdin Translations (#2131)
* New translations flycast.pot (French)
New translations for {languageName} [ci skip]
2025-12-08 14:11:01 +01:00
Flyinghead b2941a8593 ui: more l10n. add plural and context support. no l10n for debug stuff 2025-12-08 11:50:51 +01:00
flyinghead 3ad072f9aa New translations flycast.pot (French)
New translations for {languageName} [ci skip]
2025-12-08 09:37:39 +01:00
flyinghead 14374084d5 New translations flycast.pot (French)
New translations for {languageName} [ci skip]
2025-12-07 23:18:42 +01:00
Flyinghead 5c7a241897 uwp build fix 2025-12-07 21:39:13 +01:00
Flyinghead 7fcc5fa2f7 ui: update .pot and .po 2025-12-07 20:37:35 +01:00
Flyinghead cf2fe027f7 ci: bsd,switch,uwp build fixes. Better workflow names 2025-12-07 20:33:57 +01:00
Flyinghead b13685f0bb ui: switch to tinygettext for i18n 2025-12-07 19:57:03 +01:00
Flyinghead cf7b6bdcb0 ui: more localization 2025-12-06 17:11:48 +01:00
github-actions[bot] 230d971d4d Fetch translations & Recreate libretro_core_options_intl.h 2025-12-05 22:22:07 +00:00
Flyinghead 894c61ed64 libretro build fix 2025-12-04 21:41:36 +01:00
Flyinghead 82cadfde22 win: use GetLocaleInfoEx and localtime. android: build fix 2025-12-04 21:29:20 +01:00
Flyinghead 1586cbaea9 android: use system getifaddrs if available (api 24+) 2025-12-04 18:21:17 +01:00
Flyinghead 2113e4e249 localization support WIP. rewrite ini file reader/writer and more.
Support for localized dates, collation and messages.
Rewrite ini file reader/writer and command line parser.
Standardize all config stuff in the config namespace.
2025-12-04 18:17:13 +01:00
Flyinghead 5a150f4121 Merge remote-tracking branch 'origin/dev' 2025-12-03 19:23:43 +01:00
vkedwardli f178e5d76e Custom texture preloading (#2116)
* Creating a `CustomTextureSource` interface for subclassing
* `DumpReplacedTextures` option
* `PreloadCustomTextures` option
2025-12-02 17:02:19 +01:00
James 9222fa8442 Fix: DreamPicoPort locks up and causes flycast to hang (#2124)
* Use DreamPicoPort-API 1.0.2 which automatically clears USB stalls
* Getting condition in order to detect controller seems to be problematic
* Use the libusb implementation of DreamPicoPort-API on Windows because WinRT is buggy
2025-12-01 16:50:02 +01:00
Flyinghead 77359cefb2 ui: add char filter for dns names and IP addresses text input 2025-12-01 16:49:13 +01:00
Flyinghead a6dc38a35b switch: use sync keyboard applet for keyboard input 2025-11-30 18:23:15 +01:00
Flyinghead eab952fcbe ui: UWP keyboard fix. Fix DPad nav & scrolling with child windows
Detect UWP on-screen keyboard hiding and validate imgui text edit (code
by @danprice142).
Don't use list boxes for paths in Settings > General since child windows
cause issues with DPad/cursor keys navigation and thumbstick scrolling.
2025-11-29 18:06:21 +01:00
Flyinghead 1666eb0875 android: ignore touchpad axes (dualshock 4)
The touchpad also reports motion events on the same axis numbers, but
the range source is different so ignore them.
Override known axes in mapping when the gamepad is connected.
Issue #2109
2025-11-22 11:34:36 +01:00
Flyinghead 5bce763f66 Merge remote-tracking branch 'origin/dev' 2025-11-21 12:49:47 +01:00
Flyinghead 0f4fca415b ui: set VMUPath and SavePath options a single path instead of a list
Fix naming of arcade flash save files when using a custom path.
Get rid of legacy net:nvmem option.
Issue #2111
2025-11-20 16:43:27 +01:00
Flyinghead f2fe918379 android: Virtual Gamepad and Touch Mouse duplicated after app pause
These devices were recreated every time the app is unpaused.
2025-11-20 09:43:53 +01:00
Flyinghead a9be4d111c Use nowide::remove instead of unlink or std::remove 2025-11-20 09:37:04 +01:00
danprice142 ce07a7fbf5 Add user-defined paths for boxart, mappings & cheats (#2108)
* Add user-configurable paths for boxart, mappings, and cheats

Introduces new configuration options for Boxart path, Mappings path, and Cheat path, allowing users to specify custom folders for box art, controller mappings, and cheat files.
2025-11-19 15:30:30 +01:00
Flyinghead e44c03fa0e ui: reset button state when closing mapping popup and on map/unmap
Fixes button state staying on until app restart.
2025-11-19 15:29:15 +01:00
Flyinghead 1dac3695fd imgui: ImguiStyleVar must be deleted before the end of the window 2025-11-18 18:58:44 +01:00
Flyinghead 997f6179dd android: normalize axis value using min and range. Use event.actionIndex
Normalize analog axis values using InputDevice.MotionRange.min and
InputDevice.MotionRange.range.
Specify Event.actionIndex when getting axis values like SDL does.
Issue #2109
2025-11-18 18:57:02 +01:00
Flyinghead bed524f0d0 imgui: ImguiStyleVar must be deleted before the end of the window 2025-11-17 19:18:55 +01:00
Flyinghead 410b37b041 naomi: add dc microphone to king of route 66. Add cd-mic switch binding
King of route 66 uses a maple microphone for the CB-MIC feature.
Also define the mic switch button binding (button 6).
Don't add VMUs to naomi2 games since no game uses them afaik
2025-11-17 19:13:45 +01:00
Flyinghead ead4b51d6f fix savestate regression due to custom path
Issue #2111
2025-11-16 11:45:23 +01:00
Flyinghead 043bb5ee99 Merge remote-tracking branch 'origin/master' into dev 2025-11-16 11:41:40 +01:00
Flyinghead 4747e61908 vgamepad: enable touch mouse for mouse/rotary encoders arcade games
Issue #2110
2025-11-15 15:49:26 +01:00
github-actions[bot] 548cf6fe2e Fetch translations & Recreate libretro_core_options_intl.h 2025-11-14 22:21:15 +00:00
Edward Li 339d288dfb macOS: update Syphon library 2025-11-14 17:13:35 +01:00
Flyinghead 8f7e4bf2d3 aica: fix ALFO and PLFO random waveform
Fixes skating sound in Jet Set Radio
Issue #2107
2025-11-14 17:12:58 +01:00
Flyinghead 922ca3e54b cue: read pregap length from cue file and adjust track start
Use the INDEX 01 mm:ss:ff tag to determine the pregap size and add it to
the track start FAD.
Remove previous +02:00 hack for audio tracks.
Fixes Sonic Team jingle cut off in ChuChu Rocket redump cue.
Issue #2103
2025-11-14 11:12:44 +01:00
Flyinghead 4b09de2fc1 vulkan: recreate swap chain when the vulkan context becomes invalid
Fixes freeze when switching to fullscreen on gentoo.
Issue #2082
2025-11-14 10:57:14 +01:00
Flyinghead 98db7a6cd5 android: vgamepad LT and RT not set to minimum when released
LT and RT were left to 50% depressed when released.
Regression due to 7b0c106fc2
Issue #2104
2025-11-13 10:06:16 +01:00
Flyinghead 3405b5b2a6 aica: use member functions for ChannelEx instead of static ones
More enums
No functional changes
2025-11-12 20:50:31 +01:00
Flyinghead 4320685ff8 uwp: simplify activation and exit URIs handling
Use http::urlDecode to decode URIs.
Move exit URI handling to dc_exit() so that all exit paths are covered.
2025-11-12 13:40:07 +01:00
Flyinghead cd3fe7393c http: add urlDecode and tests for urlEncode and urlDecode 2025-11-11 20:43:13 +01:00
Flyinghead 2da0d392fd move oslib/directory.h function defs into a .cpp file 2025-11-11 19:24:12 +01:00
Flyinghead 8d1bf3382c android: add customisable bios and texture pack folders 2025-11-11 19:15:59 +01:00
Bobby Smith b1489d665e [Libretro] Update AV info when switching a PAL game to 60Hz 2025-11-10 14:16:02 +01:00
Flyinghead fc56bd283e fix double-nested game folder when dumping textures
Change TextureDumpPath to a single path instead of a list
Issue #305
2025-11-10 14:11:14 +01:00
Flyinghead 807e4a20ed aica: yet another LPF improvement
Use more bits for coefficients and formula closer to original hardware.
2025-11-10 13:52:21 +01:00
Flyinghead 943311752e cheats: increase max code length and input text height 2025-11-10 11:50:40 +01:00
Flyinghead e7ad12b031 rend: convert palette textures for area 1 on cpu
Only one palette is supported in the shader, so convert area 1 palette
textures (2-volume mode) on the cpu and handle them normally in the
shader.
Issue #1528
2025-11-09 15:44:48 +01:00
danprice142 b2bc6251c7 Add configurable paths for BIOS, VMU, saves, textures & dumps (#2097)
* Add configurable paths for BIOS, VMU, saves, textures & dumps

Introduces new options for user-defined folders for BIOS, VMU, savestates, game saves, texture packs, and texture dumps. Updates path resolution logic in oslib.cpp to prioritize user-specified paths before falling back to defaults.

* Add UWP support for directory and file access

Introduces UWP-specific implementations for directory handling and file access in core/oslib, including custom opendir, readdir, and closedir functions, this is so we can see subfolders properly on UWP

* Custom Paths section hidden on Android and iOS
2025-11-08 15:06:47 +01:00
Flyinghead 6f38dc3210 msvc build fix 2025-10-28 12:23:22 +01:00
danprice142 4bb32466bd Add UWP protocol activation support for ROM loading from UWP Frontends (#2095)
Adds UWP protocol activation support for ROM loading from UWP Frontends/Browsers, allows launching ROMs via SDL's `SDL_WinRTGetProtocolActivationURI()` and redirection using the 'launchOnExit' URI parameter from protocol activation in SDL_WinRTApp, Closing a Rom/Game from the quick menu or closing the app will make use of `launchOnExit` and redirect to the specified app

Implements launching a URI via Windows.System.Launcher after the game is stopped from the Exit button in the quick menu, enabling return to sender/redirection on UWP

Update SDL submodule to include SDL_WinRTGetProtocolActivationURI()
2025-10-28 11:37:16 +01:00
Rikki Gibson e26d356265 DreamConn: allow using a VMU in slot 2 (#2094) 2025-10-28 11:34:31 +01:00
Flyinghead 265c5c6c3d aica: fix EG rate and LSA > LEA behaviour from real hw tests
EG rate formula specified in the doc is correct but FRS+OCT is ignored
if negative.
If LSA > LEA, playback continues after LEA until reaching LSA. Then CA
is reset and playback stops (including looping sounds). Get rid of
Legacy of Kain hack.
2025-10-27 17:26:42 +01:00
Flyinghead 2b1eb55daa maple: flush VMU files when unloading a game
destroy maple devices when unloading a game to flush and close VMU
files.
2025-10-24 15:31:22 +02:00
Flyinghead bd136b1856 ice: vonot support
ice::term() ice on emu termination
2025-10-24 15:29:12 +02:00
Flyinghead bd8adf1da1 delete outdated dreampi dcnet binary 2025-10-22 15:35:51 +02:00
Flyinghead 11625176c2 ggpo: catch serialization exception when saving state 2025-10-22 15:33:10 +02:00
Flyinghead c64441a02f pvr: avoid pure blue video border color. change to black
Hides blue vertical bars in dinosaur king.
Issue #1246
2025-10-22 15:29:35 +02:00
Flyinghead 8e9eee246d Merge remote-tracking branch 'origin/master' into dev 2025-10-21 15:26:52 +02:00
Flyinghead d0ec876936 arm32/64 dynarec: fix crash when disabling mmu
With block linking, CpuRunning isn't tested immediately so add a special
case in DynaRBI::Relink()
Issue #893
Fixes MINIDUMP-56 MINIDUMP-6V MINIDUMP-6X MINIDUMP-CA
Fixes MINIDUMP-H8 MINIDUMP-K6 MINIDUMP-QN MINIDUMP-YZ
Fixes MINIDUMP-YM MINIDUMP-148
2025-10-21 15:24:31 +02:00
Flyinghead b19cbcbf29 android: clean up openmp stuff 2025-10-21 15:18:48 +02:00
John Lansing bf2bd7efed Move duplicate Exception class to SerializeBase 2025-10-21 12:48:39 +02:00
John Lansing d15d5be44a libretro: detect and communicate buffer overflow on save state serialization 2025-10-21 12:48:39 +02:00
Flyinghead 70c8d1d22b vk: handle acquireNextImageKHR error when resizing window
Ignoring the error leads to a deadlock since the imageAcquired semaphore
can't be signaled.
Fixes freeze when resizing window.
Issue #1620
2025-10-21 12:47:46 +02:00
JamesandRikki Gibson 3917c0181b DreamPicoPort API Update (#2079)
Co-authored-by: Rikki Gibson <[email protected]>
2025-10-20 10:48:23 +02:00
Flyinghead 6f58d204b6 arm, arm64 dynarecs: check FPU enabled after PC and block checks
Fixes hang/crash in Sega Rally 2 when exiting the Records menu.
Issue #1877
2025-10-20 10:46:30 +02:00
Flyinghead d450c84a14 rend: disable texture upscaling on mobile. hide option on desktop 2025-10-20 10:31:35 +02:00
Flyinghead 3b7036d14a android: fix init crash on 32-bit platforms 2025-10-19 15:45:40 +02:00
Flyinghead 5d628f8167 naomi: default eeprom for clubkprz. default nvmem for smarinef
Use clubk2k3 eeprom for clubk2kp and clubk2kpa.
Issue #2086
2025-10-18 18:09:29 +02:00
github-actions[bot] d1ed878446 Fetch translations & Recreate libretro_core_options_intl.h 2025-10-17 22:20:56 +00:00
Flyinghead 28ea3dc69c arcade: add CRC for all working roms. Fix mushik2k bios
All roms can now be loaded by CRC value.
Issue #1952
Fix mushik2k to use the multi-region hacked bios set to Korean region
2025-10-16 18:11:16 +02:00
Flyinghead 031a645ffc move HideCdromDrives check into ui/game_scanner 2025-10-16 18:07:09 +02:00
Flyinghead 0a526d7c94 gdb: fix race condition when stepping. Improve vCont handling
Work around race condition when stepping (CpuRunning still true in
Sh4Executor::Step() on emu thread since Step() hasn't be called yet in
main thread).
Don't advertise vCont commands that aren't supported.
Range stepping end is exclusive.
2025-10-16 17:56:39 +02:00
Flyinghead 3d594054eb libretro build fix 2025-10-15 20:30:23 +02:00
Flyinghead 3b651463dc New [config]HideCdromDrives setting to ignore physical CD/DVD drives 2025-10-15 20:00:30 +02:00
Flyinghead 4e6b5b270b vk: remove image barrier at end of oit pipeline
It seems to cause issues on snapdragon 8 elite (SM8750-AB). These GPUs
never cease to amaze me....
Partial revert of b4b4b3ab1e
Issue #2083
2025-10-15 19:58:41 +02:00
Flyinghead fd8f2e24b8 android: switch to sdk 35, min 21, ndk 29
Drop support for Android 4.* (kitkat, jelly bean)
Minimum SDK 21 (Android 5.0, lollipop)
Target SDK 35 (Android 15)
Build with NDK 29 for 16KB-page by default. Issue #1864
2025-10-14 16:47:50 +02:00
Flyinghead 82b4c55f09 fix gdb server networking
Issue #2081
2025-10-14 14:43:47 +02:00
Flyinghead 8176646c5a android: don't set section name for dynarec code cache
Use #define to declare platform-specific dynarec code buffers
Don't set section name on android to avoid error "W+E load segments are
not allowed"
2025-10-13 19:19:48 +02:00
Flyinghead 3f0dd626c1 android: update oboe to 1.10.0 2025-10-13 19:11:12 +02:00
Flyinghead 8edd8fc447 Merge remote-tracking branch 'origin/dev' 2025-10-13 16:58:06 +02:00
Flyinghead 0c7dca9cb7 sdl: move mapping parser into its own class. Add tests 2025-10-13 16:20:34 +02:00
Flyinghead 086e8bc20c android: exclude libz.so from apk 2025-10-13 16:06:47 +02:00
Flyinghead 11880bca30 atomiswave: fix lightgun games button labels
Issue #2080
2025-10-13 10:25:30 +02:00
scribam 37187467e7 cmake: lower minimum requirement 2025-10-12 11:55:35 +02:00
Flyinghead 7b0c106fc2 input: axes handling improvements
Range for all axes, including triggers, is now [-32768,32767]
Detect trigger direction when mapping and store in mapping file.
sdl: parse controller bindings string to correctly map axes.
Issue #2014
2025-10-12 11:54:16 +02:00
github-actions[bot] fd654614ae Fetch translations & Recreate libretro_core_options_intl.h 2025-10-10 22:20:45 +00:00
Flyinghead 4ee24ca612 vk: test automation fix 2025-10-10 09:01:31 +02:00
scribam 4b3704953f ci: use freebsd 14.3 2025-10-09 19:24:16 +02:00
Flyinghead 6ea9a34e8a macOS CI: update vulkan sdk version 2025-10-08 17:09:05 +02:00
Flyinghead c018d46d00 atomiswave: reset maple devices register during reset
Reset aw_maple_devs to 0 during reset.
Fixes analog controls not working after playing a mouse/trackball or
lightgun game.
Issue #2072
2025-10-06 19:39:31 +02:00
Flyinghead 400da2bdfe vk: add yet another image barrier for libretro (nvidia 30xx issue)
Also add image barrier in endFrame for libretro
Issue #1631
2025-10-06 15:42:52 +02:00
Flyinghead 3b5536dd43 new system sp games: btlracer, monomedal 2025-10-06 15:39:20 +02:00
Flyinghead 34e2f426ac build fix 2025-10-05 15:53:24 +02:00
Flyinghead a246964a99 fix some warnings 2025-10-05 15:35:52 +02:00
Flyinghead b4b4b3ab1e vk: add image barrier to work around nvidia 30xx issue
Add image barrier in VulkanContext::PresentFrame() for nvidia gpus.
Tentative fix for square glitches on nvidia 30xx series.
Issue #1631
oit: Add dependency from external to subpass 2 since vulkan's implicit
one is too relaxed.
2025-10-05 15:34:18 +02:00
github-actions[bot] af5f67c15d Fetch translations & Recreate libretro_core_options_intl.h 2025-10-03 22:21:01 +00:00
Rikki GibsonandJames 909ea496ac DreamPotato connectivity (#1989)
Co-authored-by: James <[email protected]>
2025-10-03 14:34:25 +02:00
Flyinghead 3347dc1a46 custom textures: reset available flag when initializing
Fixes crash when starting a new game without custom texture after one
that has some.
Fixes MINIDUMP-6C9
2025-10-03 14:28:31 +02:00
Flyinghead dd5e148e2b input: don't handle button input when port is set to none
Fixes physical keyboard usage on android, where the keyboard is also
handled as a gamepad and must be disabled.
2025-10-03 14:12:23 +02:00
Flyinghead 1f818ca750 naomi: fix zombrvn and zombrvne default eeproms
zombrvn: Disable free play, do analog calibration
zombrvne: Select 2-player cab
Issue #1980
2025-10-03 11:10:44 +02:00
Flyinghead ab6b95ff4d naomi: spawn needs the region number in its eeprom
The current region must be set in the eeprom, otherwise the eeprom is
reset to default and network settings are ignored.
Issue #696
2025-09-27 17:28:20 +02:00
github-actions[bot] 760c62a3da Fetch translations & Recreate libretro_core_options_intl.h 2025-09-26 22:20:52 +00:00
Flyinghead b2d8ad633d boxart: use flycast-content github repo for arcade games screenshots 2025-09-26 15:30:01 +02:00
Flyinghead f9b47b6f91 boxart: use correct file extension for images 2025-09-23 15:55:36 +02:00
Flyinghead 372ef91211 opengl: per-pixel support for GLES
Issue #2034
2025-09-23 15:53:14 +02:00
scribam 3375f6c476 deps: update sdl to version 2.32.10 2025-09-22 09:57:07 +02:00
scribam c5396a041e cmake: add windows setupapi lib 2025-09-22 09:56:56 +02:00
github-actions[bot] 851dd22664 Fetch translations & Recreate libretro_core_options_intl.h 2025-09-19 22:21:19 +00:00
github-actions[bot] ac32a80352 Fetch translations & Recreate libretro_core_options_intl.h 2025-09-12 22:20:41 +00:00
Flyinghead eff11d6a07 Merge remote-tracking branch 'origin/master' into dev 2025-09-12 18:15:23 +02:00
scribam b6c135b0c6 macOS: update libomp to version 21.1.1 2025-09-12 13:44:50 +02:00
scribam 0fe7073496 macOS: remove workaround with local/pinned/cmake from openmp formula 2025-09-12 13:44:50 +02:00
Edward Li d5c5839a92 macOS libomp: Use local/pinned/cmake in homebrew formula, update libomp to 21.1 2025-09-09 14:38:25 +02:00
Clownacy 7ac45a7e46 Remove -DCMAKE_BUILD_TYPE=Release from .gitlab-ci.yml.
There is no longer a need to set this explicitly, as libretro's CI templates have been corrected to not leave it undefined.

See this commit: https://git.libretro.com/libretro-infrastructure/ci-templates/-/commit/0241726e188a7c077dcff6cd7c1739039a79a7fb
2025-09-08 10:39:53 +02:00
github-actions[bot] 0243f81c26 Fetch translations & Recreate libretro_core_options_intl.h 2025-08-29 22:20:49 +00:00
Flyinghead 2dfa647445 naomi: cab linking support for sgtetris 2025-08-29 09:12:55 +02:00
Flyinghead 9c5408a6d3 macOS build fix
Work around brew change: https://github.com/Homebrew/brew/pull/20414
2025-08-20 14:55:37 +02:00
Eric Warmenhoven d3dcb13ef9 Update .gitlab-ci.yml 2025-08-18 14:40:14 +02:00
Flyinghead 2cb2ac23e0 force real bios for wsb2k2
Issue #1757
2025-08-18 14:39:39 +02:00
Flyinghead e38b0ac01f naomi: delete some unnecessary eeproms
Issue #2023
Fix some warnings
2025-08-14 14:30:20 +02:00
Flyinghead 09b27ddd5c maple: use PantherDC id for full controller. ui: buttons and axes state
Use actual Panther DC identifier for full controller. Fixes KISS: Psycho
Circus.
Issue #2026
Show current state of mapped gamepad buttons and axes in controller
mapping.
2025-08-13 18:26:26 +02:00
Flyinghead 33833cfd1e vonot: don't disable VM when acting as master
Issue #2037
2025-08-12 17:30:22 +02:00
Edward Li 3c5c1e0b66 Indentation should use <space> in imgui_impl_vulkan.cpp 2025-08-12 15:40:14 +02:00
Edward Li 3f446a5835 Use target_compile_definitions to disable imgui shell functions for Switch 2025-08-12 15:40:14 +02:00
Edward Li df3c676a04 chmod 644 2025-08-12 15:40:14 +02:00
Edward Li 9ff3ab618c Fix OpenGL3 and Vulkan backend 2025-08-12 15:40:14 +02:00
Edward Li ba33b8c3f7 IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS for Switch 2025-08-12 15:40:14 +02:00
Edward Li eab13e85bc minor fixes 2025-08-12 15:40:14 +02:00
Edward Li a1f1c9825a Fix EllipsisCharCount
Fonts: Rasterizing ellipsis character from dot as one glyph + avoid preloading if it not needed. https://github.com/ocornut/imgui/commit/4ff1631b316fe849da9a649cf30a79aad752d8bb
2025-08-12 15:40:14 +02:00
Edward Li 43a9c1384a Replace ImFont->FontSize with ImFont->LegacySize 2025-08-12 15:40:14 +02:00
Edward Li b4ab21a768 Reapply ImGuiWindowFlags_DragScrolling 2025-08-12 15:40:14 +02:00
Edward Li 30365d13ef replace with upstream v1.92.1 files 2025-08-12 15:40:14 +02:00
scribam f7eae0ff9e deps: update glslang (#1920) 2025-08-11 17:23:33 +02:00
sonninnos e26f170558 Libretro updates (#2033)
Add -Wno-misleading-indentation
Libretro av_info fps timing correction
Stop forcing audio muting on libretro fast-forward
Allow less strict chd extensions
2025-08-11 09:38:59 +02:00
github-actions[bot] 40e400ab08 Fetch translations & Recreate libretro_core_options_intl.h 2025-08-01 22:21:35 +00:00
github-actions[bot] 5743502cdd Fetch translations & Recreate libretro_core_options_intl.h 2025-07-25 22:21:43 +00:00
Flyinghead 8f33b63153 linux build: fix AppImageTool location 2025-07-22 15:37:54 +02:00
Flyinghead 6fca05f00e sdl: set default axis direction for all axes
Fixes regression with known gamepads.
Only use initial state for unknown controllers.
Issue #2014
2025-07-22 15:24:05 +02:00
Flyinghead 8c07a2e1d6 sdl: detect half-axes using initial state. Fix axis range and direction
Assume that full axes are roughly centered at start up and determine
which axis are half ones, and the axis direction.
Fixes driving wheel pedals range to the expected [0, 32767].
Issue #2014
2025-07-18 11:38:15 +02:00
desyn ffbe266413 bump minimal rcheevos 2025-07-15 15:52:07 +02:00
Flyinghead 5d3b7fae6b libretro: boot dreamcast bios when loading core without content
Get rid of "Boot to BIOS" core setting.
Issue #2007
2025-07-15 15:49:32 +02:00
Flyinghead 738b95d2be miniupnpc: include cstddef before miniupnpc headers
Issue #2010
2025-07-15 15:30:15 +02:00
github-actions[bot] 48c58dbd18 Fetch translations & Recreate libretro_core_options_intl.h 2025-07-11 22:21:51 +00:00
James 54b06a5c34 Recover DreamLink hardware after load state (#2003) 2025-07-10 20:32:00 +02:00
Flyinghead d3a46a1e33 windows: fix crash caused by regression
introduced by 6ea61b9
Issue #2001
2025-07-08 12:36:52 +02:00
Rikki Gibson 4fe2f4760f DreamConn: do not lock mutex multiple times 2025-07-07 11:28:27 +02:00
Flyinghead c0809d771d dcnet: support for Pro Yakyuu Team de Asobou Net!
Delete fakeTCP power smash cheat (not needed)
Add pro yakyuu team cheats
dcnet: Use same port as power smash for pro yakyuu team
2025-07-07 11:26:08 +02:00
Flyinghead 54ed92e2b0 fix ggpo regression
introduced by 4baf529ff7
2025-07-06 22:18:58 +02:00
Flyinghead 6ea61b9084 android: support 4KB and 16KB page sizes on 64-bit platforms 2025-07-06 22:16:06 +02:00
Flyinghead f3e0f09ca9 upgrade oboe and libadrenotools to latest 2025-07-06 18:51:51 +02:00
scribam 301b1a0f00 input: set InputMapping::INVALID_CODE as constexpr 2025-07-06 18:09:23 +02:00
scribam b787427446 android: update gradle and agp 2025-07-06 18:08:54 +02:00
Flyinghead 5df5c70994 dcnet: Power Smash support 2025-07-03 17:18:46 +02:00
Shockblast 75defb590b fix: added missing addrspace inclusion in settings.cpp for GDB_SERVER 2025-07-01 19:29:16 +02:00
scribam fbeaf8ba16 ci: fix switch libretro artifact location 2025-06-30 21:34:41 +02:00
github-actions[bot] 3f79b6baed Fetch translations & Recreate libretro_core_options_intl.h 2025-06-27 22:21:54 +00:00
Flyinghead 34f095a91e mingw build fix 2025-06-24 17:19:12 +02:00
Flyinghead 09247b4503 picotcp: use random local UDP port if already in use
Bind to random local UDP port if requested one is in use.
Log to NETWORK instead of MODEM.
Fix get_last_error name conflict with asio.
2025-06-24 16:54:57 +02:00
scribam 109e084e18 deps: update glslang (#1920) 2025-06-24 16:54:29 +02:00
Isaac Marovitz af043c55cd CMake Refactors (#1979)
Signed-off-by: Isaac Marovitz <[email protected]>
2025-06-24 16:33:12 +02:00
Flyinghead 04999d8969 sh4: fix wince api trace calls 2025-06-21 10:25:52 +02:00
Flyinghead 26b8684e78 serial: don't depend on SerialPTY option on windows
On windows, open serial console window when config::SerialConsole is
enabled. Ignore config::SerialPTY.
2025-06-21 10:23:22 +02:00
Flyinghead eefcb0e05d picotcp: improve ppp dump time resolution 2025-06-21 10:17:09 +02:00
github-actions[bot] 449d256995 Fetch translations & Recreate libretro_core_options_intl.h 2025-06-20 22:21:29 +00:00
Flyinghead 0897f0ed8a ui: split settings into their own files 2025-06-19 23:13:47 +02:00
Flyinghead 9bdb90e605 vk: add missing pp_Texture vertex param (naomi 2) 2025-06-19 17:48:20 +02:00
Flyinghead 5b75975237 naomi: fix zombie revenge analog stick for P2
Issue #1980
2025-06-19 17:29:25 +02:00
Flyinghead c73336a86f boxart: don't save absolute paths for images
Issue #1935
2025-06-17 17:13:27 +02:00
Flyinghead 27318443a7 more atomiswave code into its own files 2025-06-16 22:21:10 +02:00
Flyinghead df93c069f2 sdl: add sdl_gamepad.cpp 2025-06-16 18:50:37 +02:00
Flyinghead 7358f29556 naomi: refactor midiffb into its own file 2025-06-16 18:13:36 +02:00
Flyinghead 8801b2ae16 haptic: add sine effect. implement spring for midi FFB
Add sine effect to haptic api and stop using maple rumble for naomi FFB.
Emulate spring in midi FFB. Thanks to njz3 for his help on decoding the
protocol.
Don't use exponential scale for rumble when using haptic sine effect.

serialize Sh4OCache::writeBack/ThroughBufferCycles
2025-06-16 17:50:36 +02:00
github-actions[bot] b10db5a078 Fetch translations & Recreate libretro_core_options_intl.h 2025-06-13 22:21:19 +00:00
xander-will 71341a27e4 Integer Scaling + Screen-Level Linear Interpolation Options (#1976) 2025-06-13 11:59:15 +02:00
Flyinghead 7e7f645f37 sdl: use SDL_HAPTIC_STEERING_AXIS instead of SDL_HAPTIC_CARTESIAN
tentative fix for Issue #1962
2025-06-13 11:58:19 +02:00
oltolm 146e90dae6 Fix MSYS2 build (#1975)
* fix GCC build
* revert c53a1c42c6
it was fixed in https://sourceforge.net/p/mingw-w64/mingw-w64/ci/251fc7e1c3bd3509e291c1862ee745fce8550360
2025-06-13 09:55:41 +02:00
Flyinghead bb5bd71437 Merge remote-tracking branch 'origin/master' into dev 2025-06-07 16:08:03 +02:00
Flyinghead e8217ca0c5 fix input mapping regressions
Emulator keyboard bindings no longer working when UI is open (Exit).
All-ports mapping not being loaded correctly.
All-ports mapping not working on ports B,C and D.
Restore automatic binding of opposite key/axis.
caused by 64b9e51af0
2025-06-07 16:05:34 +02:00
github-actions[bot] 8f033723a1 Fetch translations & Recreate libretro_core_options_intl.h 2025-06-06 22:21:35 +00:00
Flyinghead b097aa3331 dropping iOS support
well done Gabe!
2025-06-06 09:08:14 +02:00
nexus382andJames Smith 64b9e51af0 button mapping multi binds (#1938)
Add button combination mappping support
- Implement tracking of pressed buttons in GamepadDevice
- Add ability to detect button combinations- Fix mapping system to preserve individual button mappings
- Ensure buttons can work both individually and as part of combinations
- Ensured trigger buttons can be the first button in a combination
- Maintained detection state when binding multiple buttons
- Added special handling to recognize both original and normalized trigger codes

---------

Co-authored-by: James Smith <[email protected]>
2025-06-03 16:28:51 +02:00
nexus382andJames Smith 9b91430513 Flycast UI Themes (#1929)
Added a Theme selection system.
---------
Co-authored-by: James Smith <[email protected]>
2025-06-01 19:03:42 +02:00
Flyinghead d9ec0cb3ab map dinoking P2 rock button to P1 button 4. Show on vgamepad
Remap player 2 Rock button to player 1 button 4 and display on vgamepad
so it's accessible on mobile devices.
Issue #1969
2025-06-01 10:57:59 +02:00
Flyinghead 39d68ec7fa sdl: don't reset haptic gain to 0 on exit
Issue #1963
2025-06-01 10:52:29 +02:00
github-actions[bot] a1a782df38 Fetch translations & Recreate libretro_core_options_intl.h 2025-05-30 22:21:39 +00:00
scribam acc106e988 cmake: disable link option --execute-only on openbsd 2025-05-30 18:45:55 +02:00
Flyinghead 11de0eda13 dx9: half-pixel shift left, not right
Fixes shifting of doom64 screen melt effect
Issue #1939
2025-05-30 18:45:18 +02:00
scribam a7148ad7ae cmake: use c++ extensions for alloca on netbsd/arm64 2025-05-26 19:27:55 +02:00
Flyinghead 27f19a5b54 rend: fix dithering kernel
Use the actual PVR2 dithering kernel (standard 4x4 Bayer matrix) used on
real hardware.
Fixes the screen melt effect of Doom64 (per-pixel only).
Issue #1939
2025-05-26 19:27:02 +02:00
scribam b973453317 ci: build uwp for ARM64 and Win32 2025-05-24 19:24:24 +02:00
github-actions[bot] ffaada9e9d Fetch translations & Recreate libretro_core_options_intl.h 2025-05-23 22:21:23 +00:00
Flyinghead 1953eb0eea outtrigger (US) widescreen cheat. Propeller arena modem string patch 2025-05-22 20:23:23 +02:00
scribam c3275d3c6f ci: update bsd workflows 2025-05-21 23:22:47 +02:00
Flyinghead 5e769d5cd2 Merge remote-tracking branch 'origin/master' into dev 2025-05-21 23:21:49 +02:00
Flyinghead f26e10e44a modem string patch for Mobile Suit Gundam: Federation vs.Zeon
Set minimum tx and rx speed to 0.
2025-05-21 08:28:29 +02:00
Flyinghead 3d60fc8c60 Revert "core/deps/picotcp/modules/pico_tcp.c: More checks for correct header sizes"
This reverts commit ffc32d2d86.
PR #1937
2025-05-21 08:22:35 +02:00
Flyinghead 7adeb53aee arm64 rec: fix typo in FTRC implementation
Issue #1905
2025-05-20 08:52:09 +02:00
James eacadf24a6 DreamPicoPort Mapping Updates (for maraca support) (#1940)
Add rightx and righty for DreamPicoPort (for maraca support)
Add secondary d-pad to dreampicoport mapping
Allow DreamLink device to dictate button/axis name; set custom button names in DreamPicoPort to known codes
2025-05-19 10:37:03 +02:00
Flyinghead 8e14c7f394 Merge remote-tracking branch 'origin/master' into dev 2025-05-18 20:28:41 +02:00
Flyinghead a842edb09e naomi: add mushi2k3 rom 2025-05-18 12:40:49 +02:00
github-actions[bot] e2247e4872 Fetch translations & Recreate libretro_core_options_intl.h 2025-05-16 22:21:04 +00:00
Flyinghead eb662da389 flash: add bba settings if missing. cheats for outtrigger and bomberman
Add bba config information to flash if missing. Fixes outtrigger.
cheat: Enable automode in modem connection string for Bomberman Online
and Outtrigger (US)
cheat: disable dricas auth for outtrigger (JP)
2025-05-15 16:46:54 +02:00
Flyinghead 2b79f93d6b ui: dcnet is no longer experimental 2025-05-14 19:50:14 +02:00
npt-1707 ffc32d2d86 core/deps/picotcp/modules/pico_tcp.c: More checks for correct header sizes 2025-05-10 20:56:59 +02:00
Flyinghead 892cdb7cea x86 dynarec: fix crash
Regression due to e394840344
Fixes MINIDUMP-6RC
2025-05-10 20:56:21 +02:00
Flyinghead 90ed30f70c appimage: fix some missing shared libraries
Issue #1930
2025-05-08 21:43:40 +02:00
Flyinghead 5f4eefab58 naomi: add pjustic (rev b) and pjustica. fix gunsur2 and gunsur2j
Issue #716
2025-05-06 20:04:11 +02:00
scribam 34f8ab292f deps: update sdl to version 2.32.6 2025-05-04 20:57:18 +02:00
Flyinghead 7538424efb cheat to allow The Next Tetris online features
Bypass check of modulation type and rx/tx speeds.
2025-05-04 19:31:09 +02:00
Flyinghead 3976fe1be2 readme: smaller flycast logo 2025-05-04 19:26:21 +02:00
Flyinghead c57b2e1aa7 oit: incorrect color used when src=OTHER_COLOR if dest is 2nd accum
Using src=OTHER_COLOR with destination secondary accumulator should use
the secondary accumulator color, not the final one.
Fixes dark gun in Doom 64 with Ultra graphics (bump mapping).
Issue #1771
2025-05-03 11:05:59 +02:00
Flyinghead 9cc3d1030d vk: (mali) add subpass dependency from subpass 2 to external
Add subpass dependency from the last subpass to external/top of pipe.
Fix glitches in upper left corner when using OIT on Mali GPUs.
Issue #1014
Issue #1234
Issue #1356
Issue #1497
Issue #1852
2025-05-03 11:05:49 +02:00
Flyinghead 48e964235c vk: (mali) add memory barrier in GetLastFrame
Add memory barrier between drawing and transfer.
Fix savestate thumbnail image corruption.
Issue #1922
2025-05-03 11:05:40 +02:00
Flyinghead e148fabeae libretro: don't allow saving states in a background thread
Issue #1903
2025-05-03 11:03:11 +02:00
Flyinghead d3b8a67cba naomi: add missing zombrvne rom 2025-05-03 11:01:05 +02:00
Flyinghead 03f2ef6df0 libretro: fix crash when terminating vulkan context early
Issue #1906
2025-05-03 10:57:34 +02:00
Flyinghead e1ab9af89d oit: incorrect color used when src=OTHER_COLOR if dest is 2nd accum
Using src=OTHER_COLOR with destination secondary accumulator should use
the secondary accumulator color, not the final one.
Fixes dark gun in Doom 64 with Ultra graphics (bump mapping).
Issue #1771
2025-05-02 17:46:29 +02:00
Flyinghead 3330225de4 vk: (mali) add subpass dependency from subpass 2 to external
Add subpass dependency from the last subpass to external/top of pipe.
Fix glitches in upper left corner when using OIT on Mali GPUs.
Issue #1014
Issue #1234
Issue #1356
Issue #1497
Issue #1852
2025-05-02 15:37:29 +02:00
Flyinghead 58ce9a4159 vk: (mali) add memory barrier in GetLastFrame
Add memory barrier between drawing and transfer.
Fix savestate thumbnail image corruption.
Issue #1922
2025-05-02 15:30:45 +02:00
Flyinghead 1b5c8678a4 dreampi: select best access point when connecting 2025-04-30 23:02:41 +02:00
Flyinghead c20ec680a8 Merge remote-tracking branch 'origin/master' into dev 2025-04-30 22:58:14 +02:00
Flyinghead 57cc7b4a60 Fix crash on apple silicon due to cmake 4 change
The test to set TARGET_MAC doesn't work anymore with cmake 4.
Fixes #1918
2025-04-30 16:40:25 +02:00
Flyinghead cdef7f7444 dricas auth cheat for Aero Dancing FSD 2025-04-28 21:10:10 +02:00
nexus382 f62582a4bd Screen position bug fix with multiple monitors (#1916) 2025-04-28 18:58:33 +02:00
github-actions[bot] 30e1a858da Fetch translations & Recreate libretro_core_options_intl.h 2025-04-25 22:21:57 +00:00
kapodamy b04f0eb530 Allow tweak GDB related options and see Virtual memory addresses 2025-04-24 21:32:40 +02:00
Flyinghead ef3d3bd246 iOS: fix crash
due to f3a33642f8
2025-04-23 16:39:16 +02:00
github-actions[bot] 2ca596ae20 Fetch translations & Recreate libretro_core_options_intl.h 2025-04-18 22:21:32 +00:00
James Smith 1273c06d4b Load mapping for sdl_gamepad through loadMapping() and getDefaultMapping() instead of custom implementation 2025-04-16 21:05:40 +02:00
Flyinghead 25a882341d linux AppImage build needs libfuse 2025-04-15 14:30:55 +02:00
Flyinghead 75064f5683 ci: build AppImage with ubuntu 22 2025-04-15 14:30:46 +02:00
Flyinghead 93aaf50b4f Revert "libretro: don't restart the emu in retro_serialize_size"
This reverts commit aff64d43d4.
Issue #1885, #1903
2025-04-15 14:26:57 +02:00
Flyinghead 332be9c8aa linux AppImage build needs libfuse 2025-04-12 09:52:54 +02:00
Flyinghead 77776be20b upgrade xBRZ to 1.8 2025-04-12 09:34:39 +02:00
Flyinghead f7676faa68 ci: build AppImage with ubuntu 22 2025-04-12 09:33:26 +02:00
github-actions[bot] 93f463296d Fetch translations & Recreate libretro_core_options_intl.h 2025-04-11 22:21:32 +00:00
Flyinghead aff64d43d4 libretro: don't restart the emu in retro_serialize_size
Stop the emu in retro_serialize_size and don't restart it until after
the state is saved in retro_serialize. This avoids issues when the
actual state size is greater than what retro_serialize_size returned.
Issue #1885
2025-04-11 12:02:53 +02:00
Xphalnos 240be07bbb Misc: Remove Duplicated Semicolons 2025-04-10 11:30:33 +02:00
Flyinghead 786ccf4139 vulkan: fix crash when fast-forwarding with libretro core
Issue #1901
2025-04-10 11:29:52 +02:00
Flyinghead 10a5ed6cec network: ICE improvements
F355: flush tx buffer every 34 bytes
Flush tx/rx buffers when loading a state
Use moving average for stats
2025-04-08 21:40:26 +02:00
Flyinghead b9ba3f1e63 libretro and switch build fixes 2025-04-07 19:43:12 +02:00
JamesandNexus382 34fda43d9c DreamPicoPort fixes/enhancements (#1892)
* added getFunctionDefinitions
* Set DreamPort device default deadzone to 0% while preserving user customization
* Fixed default dead zone 0% for DreamPicoPort; set UsePhysicalVmuMemory default to true
* Use DisabledScope for UsePhysicalVmuMemory; moved DreamLinkGamepad::getDefaultMapping() to protected scope to match parent
* Set unique ID for DreamPicoPort devices so they enumerate the same way by flycast on every load
* Implement DreamLinkGamepad::resetMappingToDefault() and set C, D, and Z buttons for DreamPicoPort
---------
Co-authored-by: Nexus382 <[email protected]>
2025-04-07 19:23:14 +02:00
Flyinghead b602cc9c57 network: add ice/websocket match code system for battle cable 2025-04-07 19:22:02 +02:00
Flyinghead 63534c5d56 add websocket++ and libjuice as submodules 2025-04-07 18:06:44 +02:00
Flyinghead 0267de4997 upgrade xbyak to 7.23.1. Convert to git submodule 2025-04-07 17:58:21 +02:00
Xphalnos 56c00b0eb5 [GUI] Adding Rounded Borders 2025-04-07 09:06:12 +02:00
Flyinghead 3114394019 Merge remote-tracking branch 'origin/dev' 2025-04-05 22:30:31 +02:00
github-actions[bot] e5f13b6858 Fetch translations & Recreate libretro_core_options_intl.h 2025-04-04 22:21:17 +00:00
Flyinghead 3193d2cf5d quick'n'dirty cmake 4.0 support 2025-04-02 14:20:33 +02:00
scribam 0f18e2e167 deps: update sdl to version 2.32.4 2025-04-01 17:17:22 +02:00
Flyinghead 5908b1a84a picoppp: send UDP data synchronously
Use send_to instead of async_send_to for UDP sockets. Set socket to
non-blocking and discard data if socket full. Tentative fix for
corrupted Speed Devils Online UDP packets.
Fix uncaught exception if dns server name can't be resolved.
Use lambda instead of std::bind.
2025-04-01 17:16:39 +02:00
Flyinghead 4d6168dd0b dcnet: find best access point 2025-04-01 17:07:54 +02:00
scribam 2d1c602a69 ci: remove ninja installation for macos runner 2025-03-30 16:00:45 +02:00
Flyinghead 130675aae3 gles3: use GL_R8 internal format for fog texture
regression due to 3469b7f
Issue #1886
2025-03-28 11:12:30 +01:00
Xphalnos 75d5cc4d63 Use DXGI 1.6 and D3D11_4 2025-03-27 17:42:48 +01:00
Isaac Marovitz 5a110fd666 Replace sprintf with snprintf (#1884)
Signed-off-by: Isaac Marovitz <[email protected]>
2025-03-25 18:47:07 +01:00
Flyinghead 13436a4dda support for (some) encrypted cheats 2025-03-23 18:07:56 +01:00
James 2631706fe2 Enable physical VMU memory access (#1881) 2025-03-22 15:59:42 +01:00
Xphalnos ea6d5f8732 Update xxHash to 0.8.3 + Use faster algorithm 2025-03-22 15:58:22 +01:00
Flyinghead 305cae496f dcnet: don't try to detect ppp frames on output. send data immediately 2025-03-22 15:24:23 +01:00
Flyinghead 416085980f dcnet: empty modem buffer on init. Allow hostname override in emu.cfg 2025-03-19 19:46:16 +01:00
RTA 8b35fb80b4 Reset static device state on core unload to ensure input descriptors refresh 2025-03-17 15:36:18 +01:00
Flyinghead 5c1249c55f ci: another switch build fix attempt
gitsome's gh isn't compatible with the github one. Specify rclone
version to avoid gh use.
2025-03-17 15:00:40 +01:00
Flyinghead fac44e4a2f ci: switch build fix. Filter *.json files on android 2025-03-17 14:41:43 +01:00
Flyinghead 4ea317d51f ci: use rclone for android and switch builds 2025-03-17 13:50:12 +01:00
Flyinghead 310d5e612e ci: use rclone instead of aws cli 2025-03-17 10:26:23 +01:00
Flyinghead 62778b1a68 ci: testing scaleway 2025-03-16 23:33:06 +01:00
Flyinghead 604415b0d2 ci: trying s3 cp instead of sync 2025-03-16 22:05:15 +01:00
Flyinghead 49ea1135ee ci: ditch configure-aws-credentials 2025-03-16 20:56:07 +01:00
Flyinghead 46e2d52b75 store build artifacts on OVH 2025-03-16 20:31:17 +01:00
github-actions[bot] 44f77408e4 Fetch translations & Recreate libretro_core_options_intl.h 2025-03-14 22:21:10 +00:00
scribam 2860aa96f4 deps: update sdl to version 2.32.2 2025-03-12 18:30:06 +01:00
scribam 8b0a5fa480 deps: update oboe to version 1.9.3 2025-03-12 18:30:06 +01:00
scribam b150ba2b62 android: update project 2025-03-12 18:30:06 +01:00
github-actions[bot] 48bce25820 Fetch translations & Recreate libretro_core_options_intl.h 2025-03-07 22:19:55 +00:00
Eric Warmenhoven 562f78cd71 libretro: build osx-x64 build on new builder 2025-03-05 21:25:39 +01:00
github-actions[bot] 9e0573aa98 Fetch translations & Recreate libretro_core_options_intl.h 2025-02-28 22:21:22 +00:00
Flyinghead d23b3b6bc7 rcheevos: include flycast version in user-agent header
Issue #1798
2025-02-27 11:26:52 +01:00
Flyinghead 1d9f8ab438 custom textures: fix static deinit order issue 2025-02-27 11:20:31 +01:00
Flyinghead df3c075fba Force TV composite for Caesar's Palace 2000 and PAL for the EU edition
Issue #1851
2025-02-27 11:00:48 +01:00
Mike Kosek 9cdd0aab9f Rename DreamPort to DreamPicoPort (#1850)
* Renamed DreamPort to DreamPicoPort
* Removed fallback to deprecated config keys
2025-02-22 08:11:05 +01:00
github-actions[bot] e4d9220f3f Fetch translations & Recreate libretro_core_options_intl.h 2025-02-21 22:21:05 +00:00
Flyinghead 0bf9c64b1b Merge remote-tracking branch 'origin/dev' 2025-02-18 09:27:07 +01:00
JamesandMike Kosek 4e74619d9e Harden serial comm interface (#1847)
* Harden serial interface
* Fixed build errors
* Minor tweaks
* Automatically attached A->A, B->B, etc
* Interfaces go in decending order
* Do a modulo in case I decide to move interface numbers
* Do specifically mod 4
* Call SDL_JoystickGetDeviceInstanceID which seems to help with a Windows bug
* Made MapleDevices smart pointers so they can freely be swapped out without leaking
* Fixed issues some issues reported by kosekmi
* Added missing bracket
* Fixed another compile issue
* Fixed a missing else
* If device had no serial number, fall down to checking name
* Use new DreamPort firmware dynamics
* Added missing parens
* Fixed screen blanking issue
* Added const
* Reset VMU Screen on game/emulator exit
* Added gameTermination() hook to hardware gamepad
* Send SW port on game termination
* Added checks so port is only sent if data is valid
* Fixed bug: wait for write to complete in sendCmd
* Fixed bug leading to multiple pointers to VMU and Rumble pack
---------

Co-authored-by: Mike Kosek <[email protected]>
2025-02-16 17:36:57 +01:00
Flyinghead 0414a90500 dcnet: don't use timer for modem. better error reporting. race condition
Use io_context::post() instead of a timer to read from modem.
Notify user if connection to DCNet fails.
Fix race condition/crash with BBA.
Use lambdas instead of std::bind.
2025-02-16 17:33:56 +01:00
github-actions[bot] 5866e97d18 Fetch translations & Recreate libretro_core_options_intl.h 2025-02-14 22:21:01 +00:00
scribam 387e2427b4 deps: update sdl to version 2.32.0 2025-02-10 18:13:12 +01:00
Flyinghead 5187258f4b dcnet: BBA support
Stop network service when bba is reset. Start it on first frame out.
dcnet: close connection on dhcp release
picoppp: close all sockets and acceptors when stopping.
2025-02-10 18:12:24 +01:00
e1da1c3a55 CMake: Change core install location to lib/libretro (#1842)
* CMake: Change core install location to lib/libretro

* fix CI build artifacts location

---------

Co-authored-by: Andrew Wong <[email protected]>
Co-authored-by: Flyinghead <[email protected]>
2025-02-10 13:25:34 +01:00
Flyinghead 84356e3b26 dreampi.py: shake off the modem on first run (from scrivani) 2025-02-08 16:20:47 +01:00
Flyinghead c7499df3a8 cheats for Aero Dancing i & i2 in BBA mode 2025-02-08 16:17:15 +01:00
github-actions[bot] 03f7a0f605 Fetch translations & Recreate libretro_core_options_intl.h 2025-02-07 22:20:30 +00:00
Flyinghead f3c838d19d dricas auth cheat for Aero Dancing i - Jikai Saku Made Matemasen 2025-02-05 18:29:56 +01:00
Flyinghead d6f3ca986d fix from jscrivani to work around the initial failed connection 2025-02-05 18:28:12 +01:00
Flyinghead b9df7d3469 network digital outputs: check config option when game starts
Avoid the need to restart when enabling or disabling this option
Send game name to newly connected sockets
ignore SIGPIPE (telnet)
Log network errors
2025-02-04 17:46:02 +01:00
Flyinghead bf1d4a56ae gdrom: fix savestate compatibility issue
consequence of c860807fef
2025-02-04 17:27:47 +01:00
Flyinghead a682e20bbd modem: modem must hang up as soon as reg20 is written
some games don't do a full reset and the modem would stay connected.
Remove debug file dumps.
2025-02-04 17:20:15 +01:00
Flyinghead 5b9dd96064 option to set the ISP username in flash rom 2025-02-04 17:17:38 +01:00
Flyinghead a99a72589b better cheats for dricas auth 2025-02-04 17:14:01 +01:00
James 77ed9c20de Connect to DreamConn only once registered (#1828) 2025-02-03 18:19:22 +01:00
Flyinghead 7cb0fe53d7 add cheats to bypass dricas authentication
Aero Dancing i
Daytona USA (JP)
Sega Tetris
Golf Shiyou Yo 2
Hundred Swords
2025-02-03 18:18:28 +01:00
Flyinghead 3db0fce9b6 bypass dricas auth in aero dancing i 2025-02-02 17:12:54 +01:00
Flyinghead 6a15e7a3aa rend: LoD0 of VQ YUV textures is invalid. Use LoD1 instead.
Fixes background magenta textures in WSB2K2. Issue #1038
2025-02-02 17:11:22 +01:00
github-actions[bot] 431d71de5e Fetch translations & Recreate libretro_core_options_intl.h 2025-01-31 22:20:31 +00:00
Flyinghead 914fa29d31 gdrom: increase dma delay for small DMA transfers
Fixes WSB 2K2 freezes.
Issue #1038
2025-01-31 18:09:33 +01:00
Flyinghead c143cae09b disable Daytona USA (US) widescreen cheat
breaks online features
2025-01-31 15:32:18 +01:00
James a35e8214df Serial comm update (#1820)
* Broke apart DreamConn and DreamcastControllerUsb implementations; added serial timeouts; process serial in thread; removed crc from DreamcastControllerUsb sdl definition

* Added missing include statements

* Changed INFO_LOG to NOTICE_LOG on a couple of lines

* Clear the read queue once string is pulled off of it
2025-01-28 17:27:26 +01:00
Flyinghead d84108de32 maple: yet another maple timing change
Use 2 Mb/s for console and 740 Kb/s for devices.
Fixes Silent Scope vmu load issue at boot. Issue #1796
D+Vine has issues detecting A and B presses with one controller
connected but it does work eventually. No issue with more than 1
controller. Issue #1279
Power Drift only boots with one controller connected. Crashes with 2 or
more.
2025-01-28 17:26:22 +01:00
Flyinghead 1513c6cab8 msvc build fix 2025-01-27 17:47:22 +01:00
Mike Kosek 34104724a6 Added config file override for DreamcastControllerUsb Serial Device 2025-01-27 17:30:46 +01:00
Flyinghead b70c2791b2 dynarec: proper ftrc implem. (arm32/64) Use double for fipr/ftrv
Use double for canonical FIPR and FTRV on all platforms.
Fix interpreter implementation of FTRC.
Fix canonical implementation of cvt_f2i (FTRC).
arm32: use Vfma instead of Vmla for FMAC. Vfma does not a fused
muliply-add, Vmla doesn't.
arm32: Use canonical implementations of FIPR and FTRV.
arm32,arm64: Correct implemetation of cvt_f2i (FTRC)

Fixes desync with NBA 2k1/2k2 online games.
2025-01-27 17:30:06 +01:00
scribam ccdd53ee0e deps: update sdl to version 2.30.11 2025-01-25 17:02:56 +01:00
scribam 57a3e4ca53 ci: update netbsd version 2025-01-25 17:02:56 +01:00
scribam b92ac1544e android: update project 2025-01-25 17:02:56 +01:00
Mike Kosek 26d386f833 Fixed handling of asio::io_context 2025-01-25 17:02:18 +01:00
Mike Kosek ce0060126e Now adding mappings for Dreamcast Controller USB during input_sdl_init() 2025-01-25 17:02:18 +01:00
Mike Kosek 4389a3ffa6 Reverted Dreamcast Controller USB mapping workaround 2025-01-25 17:02:18 +01:00
Flyinghead b3fa453d75 dreamconn: asio::serial_port isn't defined on all platforms 2025-01-25 17:02:18 +01:00
Mike Kosek 32c274f407 Updated serial device search on Windows to select only matching VID/PID 2025-01-25 17:02:18 +01:00
Mike Kosek cb2d3e3776 Maple Message to Dreamcast Controller USB now prefixed for compatibility with newest version 2025-01-25 17:02:18 +01:00
Mike Kosek 28f5dd983e Now properly setting and checking left/right Trigger 2025-01-25 17:02:18 +01:00
Mike Kosek 160828a4c7 Overrode default mapping for DreamcastControllerUsb on MacOS/Windows 2025-01-25 17:02:18 +01:00
Mike Kosek aee932808e Removed unused function getDreamcastControllerType() 2025-01-25 17:02:18 +01:00
Mike Kosek 77636391fc Enabled the usage of VMUs and Rumble Packs with Original DC Controllers 2025-01-25 17:02:18 +01:00
Flyinghead 944af44c7f naomi: some digital outputs still missing for f355
Lamps use 14 bits of output in f355.
2025-01-25 17:00:48 +01:00
github-actions[bot] 5c27648699 Fetch translations & Recreate libretro_core_options_intl.h 2025-01-24 22:21:08 +00:00
Flyinghead 7ef35eaf68 dreampi: fix paths 2025-01-24 18:26:44 +01:00
Flyinghead bb733323ce dcnet utility for dreampi 2025-01-24 18:13:56 +01:00
Flyinghead 1b6bf25e7a naomi: broadcast digital outputs even when using FFB drive
The first byte is for lamps, the next two are for FFB.
Fixes missing lamp notifications when broadcasting digital outputs
(F355).
2025-01-23 18:40:24 +01:00
Flyinghead aa65b81f89 switch build fix 2025-01-23 18:34:58 +01:00
Wunkolo da9f030a0e vk: Refactor swapchain format selection
Use a series of stable-partitions to sort the list of available formats
to find the best candidate surface-format/color-space that is a non-sRGB
format being presented in an sRGB color-space. Vulkan mandates that all
surface formats that have SRGB forms must also support a UNORM form.

This is basically just RGBA8/BGRA8 on all platforms still, but in a way
that is still capable of falling back to secondary formats in a stable
way in the case that the primary choice is not available.  Mobile
devices especially have a LOT of secondary HDR surface formats and other
weird formats that can be used to present such as RGBA16 or RGBA565.
With stable partitions, if we can't get our best option then there is
always a "next best thing" to fall back on rather than relying on the
driver-order.
2025-01-22 18:28:55 +01:00
Wunkolo a0e1eb0005 vulkan: Allow native RGB8 screenshot framebuffers when available
Some notable devices support native RGB8 color-attachments:
https://vulkan.gpuinfo.org/listdevicescoverage.php?optimaltilingformat=R8G8B8_UNORM&featureflagbit=COLOR_ATTACHMENT

This removes the need to do a manual RGBA->RGB format conversion on the CPU in favor of a direct memcpy from the downloaded texture, when available.
2025-01-22 18:27:20 +01:00
Flyinghead 5cc15429cd Force Native Depth Interpolation on UWP/Xbox. UWP build fix 2025-01-22 18:26:29 +01:00
Flyinghead 18656f5986 picoppp: terminate MiniUPnP in a background thread 2025-01-21 18:21:47 +01:00
Flyinghead 536be34853 dcnet: update emu network state when connected 2025-01-21 18:19:39 +01:00
Flyinghead 5b513cac5b gl: use textureProj for palette texture sampling when possible/available
Fixes UV precision issue when doing the Z-divide manually.
Issue #1804
2025-01-21 18:18:05 +01:00
Flyinghead 5efdf58e85 custom texture: skip updating a texture if its hash hasn't changed
Some textures are frequently updated because of their location in vram,
close to a hotspot. This causes the custom texture to never be loaded.
This change will skip the unneeded texture update, allowing the custom
tex to replace it when available.
Issue #1812
2025-01-21 18:12:10 +01:00
github-actions[bot] a93f3697d6 Fetch translations & Recreate libretro_core_options_intl.h 2025-01-17 22:20:48 +00:00
Flyinghead b98e833c57 uwp: define _WIN32_WINNT to avoid compile issues with asio 2025-01-17 17:46:49 +01:00
github-actions[bot] 2e89848041 Fetch translations & Recreate libretro_core_options_intl.h 2025-01-10 22:20:35 +00:00
Flyinghead bb4ba3ed89 dcnet: libretro support 2025-01-09 19:01:50 +01:00
Flyinghead a5a338d408 experimental DCNet cloud service 2025-01-09 18:48:29 +01:00
Edward Li 3114344414 [macOS] Fix booting game stuck at "Starting..." when Video Routing is enabled with OpenGL 2025-01-09 13:59:54 +01:00
oltolm 20ba79668f fix compiler warnings 2025-01-09 13:59:21 +01:00
oltolm 7a4f9d8667 CMake: fix build on Windows 2025-01-06 19:46:52 +01:00
Wunkolo 22bff1b017 cmake: Use set_target_properties to set C++ standard
This stops dependencies from inheriting a global C++20 standard setting
and instead designates the flycast target alone to be a C++20 project.
2025-01-05 22:06:37 +01:00
Wunkolo 9344856c7e ggpo: Fix malformed template constructor
This form is not needed for a template-class's constructor.
Fix for C++20 builds
2025-01-05 22:06:37 +01:00
Wunkolo b2c1d134e1 deps: Update luabridge to 2.8
From 2.6 to 2.8. Includes some C++20 fixes.
2025-01-05 22:06:37 +01:00
Wunkolo 160d3e7ef3 cmake: C++20 enablement
Enables the C++ 20 standard
2025-01-05 22:06:37 +01:00
Flyinghead 3cf4808033 fix perf regression on macOS and iOS. Add Silent Scope (JP) identifier.
Regression introduced in f3a3364
CopyToVRAM wasn't enabled for Silent Scope (JP). Issue #1796
2025-01-05 22:06:37 +01:00
Flyinghead 1bd894f941 rend: reset scissoring before drawing final modvol quad
See d618abc320
Issue #1797
2025-01-05 22:06:37 +01:00
Edward Li 8dc55721d0 Generate Xcode project which can support both iOS and iOS Simulator 2025-01-05 22:06:37 +01:00
scribam c94deaee9d build: drop unsupported architectures 2025-01-05 22:06:37 +01:00
scribam 95583583ca ci: force ubuntu-22.04 on libretro-x86_64-pc-linux-gnu target 2025-01-05 22:06:37 +01:00
Flyinghead 42752acef5 Fix crash when reading 2448-byte sectors
Fixes MINIDUMP-5J0, MINIDUMP-5M7, MINIDUMP-5M8, MINIDUMP-5MA,
MINIDUMP-5MF
2025-01-05 22:06:37 +01:00
github-actions[bot] 45c700ab60 Fetch translations & Recreate libretro_core_options_intl.h 2025-01-05 22:06:37 +01:00
Flyinghead a3902fc278 sdl: disable rumble when rumble power is set to 0
Issue #1766
Issue #1783
2025-01-05 22:06:37 +01:00
Flyinghead 0606f3e63e ios: make the keyboard remappable 2025-01-05 22:06:37 +01:00
Flyinghead 0558c957e8 libretro: set an SDL hint to keep flycast SIGSEGV handler
Thanks to mrfixit2001 for helping troubleshoot the issue.
2025-01-05 22:06:37 +01:00
github-actions[bot] 2ca9187137 Fetch translations & Recreate libretro_core_options_intl.h 2025-01-05 22:06:37 +01:00
Flyinghead 5add29cbed fix perf regression on macOS and iOS. Add Silent Scope (JP) identifier.
Regression introduced in f3a3364
CopyToVRAM wasn't enabled for Silent Scope (JP). Issue #1796
2025-01-05 10:21:54 +01:00
Flyinghead 5a1c3f80f5 msvc32 build fix 2025-01-02 13:55:39 +01:00
Flyinghead a0e8e9a9df libretro: windows build fix 2025-01-02 12:11:45 +01:00
Flyinghead 45f4378184 network: use asio for modem/bba. DirectPlay4 support
DirectPlay4 support: StarLancer, PBA Bowling
miniupnp: remove unused stuff
2025-01-02 11:27:11 +01:00
Flyinghead c7d030c2e6 uwp: enable vmem. fix dynarec crash. windows: dll loading utility
uwp: Fix crash in x64 dynarec when rewriting due to wrong unprotect
range.
uwp: load MapViewOfFileEx dynamically to map regions at a given address.
dll load and function lookup utility.
2025-01-02 11:13:25 +01:00
Flyinghead 2bee6b1ce4 picotcp: fix msvc build. reduce logging 2025-01-02 11:01:58 +01:00
Flyinghead 522505273e miniupnpc: minissdpc.c: fix memory allocation error
backport
https://github.com/miniupnp/miniupnp/commit/9698973600e639ddf0ceb0ee565d7297598486fe
2025-01-02 10:57:38 +01:00
Flyinghead 0481f5464d misc non-functional changes 2025-01-02 10:54:19 +01:00
Flyinghead 7478476f9c multithreading utilities (periodic, worker thread) 2025-01-02 10:50:46 +01:00
Flyinghead 76c3695f6e log: support udp log server 2025-01-02 10:35:27 +01:00
Flyinghead e18ada7225 rend: reset scissoring before drawing final modvol quad
See d618abc320
Issue #1797
2024-12-31 18:22:07 +01:00
Edward Li f3a33642f8 Generate Xcode project which can support both iOS and iOS Simulator 2024-12-30 12:23:27 +01:00
scribam 2f03c1b147 build: drop unsupported architectures 2024-12-30 12:22:59 +01:00
scribam b7e2f5e489 ci: force ubuntu-22.04 on libretro-x86_64-pc-linux-gnu target 2024-12-30 12:22:28 +01:00
Flyinghead d01cbde41c Fix crash when reading 2448-byte sectors
Fixes MINIDUMP-5J0, MINIDUMP-5M7, MINIDUMP-5M8, MINIDUMP-5MA,
MINIDUMP-5MF
2024-12-30 12:20:29 +01:00
Flyinghead 11068012fe picotcp: support threads with msvc. Fix msvc pragma push issue
Enable threading support with msvc, similar to posix.
Fix missing pragma pop after picotcp include files
2024-12-30 12:15:36 +01:00
Flyinghead a06791780d Merge remote-tracking branch 'origin/dev' 2024-12-29 10:59:49 +01:00
Flyinghead ee1a7167f6 dreamconn: open pause menu when LT+RT+Start is pressed
Issue #1305
2024-12-28 15:39:11 +01:00
Flyinghead 10aaec1619 dreamconn: send data with socket to avoid fragmentation. Build fix
Issue #1305
2024-12-28 12:21:26 +01:00
github-actions[bot] 32d8d9a8c3 Fetch translations & Recreate libretro_core_options_intl.h 2024-12-27 22:20:31 +00:00
Flyinghead 553f77c675 dreamconn: send buzzer messages. Rename controller. Use asio iostream
Issue #1305
2024-12-27 18:47:12 +01:00
Flyinghead 9402981b43 net: add asio. use it for the gdb agent 2024-12-27 18:39:13 +01:00
Flyinghead 9038ef6d8a sdl: disable rumble when rumble power is set to 0
Issue #1766
Issue #1783
2024-12-26 16:31:23 +01:00
Flyinghead 1d290560e0 picotcp: accept PSH flag in SYN+ACK packets
Windows CE adds the PSH flag to SYN+ACK packets, which isn't normally
valid, so just ignore the flag. See dcgamespy filter in dreampi.
2024-12-26 13:04:07 +01:00
Flyinghead 59e844db15 picotcp: Integer Overflow in pico icmp4
upstream
https://github.com/virtualsquare/picotcp/commit/cc923d2a1221d2066dc9270fb86c5c43635ce06e
2024-12-26 12:38:26 +01:00
Flyinghead 6853238c8b picotcp: Discard incoming TCP segments with zero-len options
upstream
https://github.com/virtualsquare/picotcp/commit/7aa288510a033691c3f09e2c43e10f07e24434b7
2024-12-26 12:12:48 +01:00
Flyinghead f0aa1abf89 picotcp: Fixed bug in tcpopt_len_check (rolling back index).
upstream
https://github.com/virtualsquare/picotcp/commit/f569ed8fb66630fa4a4dc59259253767da67b23a
2024-12-26 12:03:09 +01:00
Flyinghead cfd3677746 picotcp: add socket event before socket is deleted
Socket callback is called with PICO_SOCK_EV_DEL just before the socket
is deleted. After returning from the callback, the socket pointer is no
longer valid.
2024-12-26 11:45:58 +01:00
Flyinghead 50a10598e4 picotcp: Resolved memory leak
upstream
https://github.com/tass-belgium/picotcp/commit/83527c69d3f69ba2b049b827c4f80c0633dce390
2024-12-26 11:33:26 +01:00
Flyinghead 9bfd48cf40 ios: make the keyboard remappable 2024-12-21 12:26:16 +01:00
Flyinghead b72750c7d5 libretro: set an SDL hint to keep flycast SIGSEGV handler
Thanks to mrfixit2001 for helping troubleshoot the issue.
2024-12-21 12:25:30 +01:00
Flyinghead b9fdd5070b dreamconn: detect dreamconn+ with VID/PID. Send maple data as text.
Create DreamConn gamepad when detected.
Send/receive maple data in ascii dump form.
Simplify maple device creation.

Issue #1305
2024-12-20 20:02:58 +01:00
Flyinghead 6c3d77b012 more windows build fix 2024-12-16 18:14:21 +01:00
Flyinghead 7fee0d2d29 cheat to work around fur fighters hanging
Root issue seems to be TCNT0 returning the same value twice, which
breaks the game calculation of the game speed/frame rate.
Issue #145
2024-12-16 17:54:02 +01:00
Flyinghead dfd4dbebc4 fix windows build 2024-12-16 17:34:38 +01:00
Flyinghead 34a5e7f47d input: dreamconn+ support prototype
Issue #1305
2024-12-16 17:17:45 +01:00
Flyinghead 3f8d645c42 rend: last frame was sometimes presented after the game is stopped
When the clearLastFrame flag is set, renderers should return false from
Present() and RenderLastFrame() until a new frame is rendered.
2024-12-15 15:55:28 +01:00
Flyinghead ecd0305a60 fix build without dynarec 2024-12-14 19:43:32 +01:00
Flyinghead 667e3906d8 sh4: work around previous SCIF issues when loading a state
Force SCIF_SCBRR2 to 8 bits when loading a state.
See e03e11b8a9 and
6115a918b2.
2024-12-14 19:13:05 +01:00
Flyinghead e5b1d56a7c rend: split texture conversion routines into their own file 2024-12-14 19:07:18 +01:00
Flyinghead d789b57412 rend: get rid of globals for fog/palette updates & tex cache flush
Add state vars to Renderer
Use events to detect loading a state and terminating the game.
Don't present last rendered frame after game terminated.
2024-12-14 17:00:51 +01:00
Flyinghead 825778445a ui: show boxart cover when starting a game 2024-12-14 16:54:18 +01:00
Flyinghead 20517cf0da vgamepad: enable touch mouse when lightgun used
Use unique touch mouse class for iOS and Android.
Enable touch mouse for arcade lightgun games or when maple device A is a
lg. Disable it otherwise.
android: only display controllers that actually send events, including
system mouse and keyboard. Use separate Touch Mouse and System Mouse.
iOS: fix missing button input for touch mouse. Don't bubble up touch
events that hit vgampad buttons or controls.
2024-12-14 16:18:35 +01:00
github-actions[bot] 989d3b1370 Fetch translations & Recreate libretro_core_options_intl.h 2024-12-13 22:21:39 +00:00
Flyinghead 421245aeba lightgun xhair: centralize logic in crosshairNeeded() 2024-12-13 17:21:32 +01:00
Flyinghead 686f08e7dd vgamepad: hide btn0 and map reload to btn1 for lightgun games 2024-12-13 16:49:57 +01:00
Flyinghead 4af1d096de audio: reset buffer on loadstate/term. Fix null audio driver on windows
Eliminate audio clicks when loading a state or starting the next game.
Fix overflow in null audio driver on windows. Detect fast forward and
reset time counter.
2024-12-13 15:58:32 +01:00
Flyinghead 27a0497dd5 win32: fix opening CD drive on command line. libretro build fix 2024-12-12 15:52:07 +01:00
Flyinghead 9ea0563a7a gdrom: stop cdda playback when reaching session lead out
Issue #1654
2024-12-12 14:27:23 +01:00
Flyinghead a46677e64e ui: add cancel button when inserting a disk
Issue #1566
2024-12-12 10:17:45 +01:00
Flyinghead a7f2008763 rend: support planar VQ textures
Fixes gens4all emu in teenage mutant ninja turtle collection.
Issue #868
2024-12-12 10:14:30 +01:00
Flyinghead 53e0f12c22 win32: force libcdio static link
Issue #1654
2024-12-12 09:57:18 +01:00
Flyinghead 34961daaec gdrom: add support for hardware CD-ROM devices
Use libcdio to read CD/DVD/BD drives (linux, windows, bsd)
Get rid of old ioctl win32 driver.
Add detected CDROM devices to game list.
Issue #1654
2024-12-11 11:25:50 +01:00
Flyinghead f5389bcd0b battle cable: notify user when data first received from peer
Document SCIF register bits.
2024-12-11 11:04:44 +01:00
Flyinghead 67eee05c14 lightgun: wiggle the reported lightgun position in a 2x2 square
Fixes claychal not registering shots in menus.
2024-12-11 10:41:53 +01:00
Flyinghead bb1b1059d4 sh4: SCIF DR bit can't be reset if rx fifo isn't empty
Fixes manic panic periodic touchscreen errors.
2024-12-11 10:37:48 +01:00
Flyinghead 94f35ca54f arcade: add input descriptors for most games 2024-12-09 16:09:45 +01:00
Flyinghead 1507097bcd naomi: set offscreen sensor when reloading. fix wldkicks PCB inputs
Most games using analog inputs for lightguns also have an offscreen
sensor (lupinsho, mok, hotd2, confmiss). Activate it when reloading or
shooting offscreen.
Fix World Kicks PCB inputs.
2024-12-09 16:02:30 +01:00
Flyinghead e4599e36ed Merge remote-tracking branch 'origin/master' into dev 2024-12-08 10:47:31 +01:00
Flyinghead 15617c1816 ssa: fix regression
due to fff03f64a3
Issue #1773
2024-12-08 10:40:44 +01:00
scribam fb64fc418e ci: update freebsd and openbsd versions 2024-12-07 21:04:17 +01:00
scribam 5656370388 deps: update sdl to version 2.30.10 2024-12-07 21:03:49 +01:00
Flyinghead 354d649ebd Merge remote-tracking branch 'origin/master' into dev 2024-12-07 20:38:55 +01:00
Johan Mattssonandflyinghead fff03f64a3 ssa: Fix wrong opcode comparison (#1769)
* ssa: Fix wrong opcode comparison

* ssa: handle 32 bits shift case first (shld, shad)

---------

Co-authored-by: flyinghead <[email protected]>
2024-12-07 18:59:14 +01:00
Flyinghead a99aa5217b sdl: don't run null haptic effects. Stop effects instead
Tentative fix for Issue #1766
2024-12-07 18:57:40 +01:00
Flyinghead 89abb7925b Pro Pinball needs copy to vram. remove Nightmare Creatures widescreen
Issue #1763
2024-12-07 10:04:36 +01:00
Flyinghead dea8e74182 better CI job names 2024-12-04 18:19:34 +01:00
Flyinghead 92c5892d4c android: fix scaling when editing vgamepad. vgamepad code clean up 2024-12-04 18:17:11 +01:00
Flyinghead 21f9e9fbc2 android,ios: arcade vgamepad layout. android vgamepad rewrite
Refactor common virtual gamepad code.
Distinct layouts for console and arcade.
Add arcade buttons 5 and 6, insert card button, service mode toggle.
System SP support
2024-12-03 21:04:51 +01:00
Flyinghead 78fa3ee09e vulkan: delay updating imgui texture when driver has just been reset
Fixes crash when selecting a custom gamepad layout .png (android)
2024-12-03 20:42:54 +01:00
Flyinghead de1584d97c systemsp: input remapping. Input desc for mushiking, dinoking, lovebery
Allow input remapping for SystemSP.
Add input descriptors for barcode games: mushiking, dinoking and
love&berry
2024-12-03 20:16:56 +01:00
Flyinghead a40c51e682 gdrom: fix deserialization crash
regression due to c860807fef
Issue #1755
2024-12-03 18:33:58 +01:00
Flyinghead c860807fef gdrom: reduce dma buffer size. reios: schedule dma reads by chunks
Reduce gdrom dma buffer size to 16 sectors from 32.
Limit serialization of dma and pio buffers to actual content.
reios: schedule transfer of dma data in chunks.
Fixes Soul Calibuf audio drop outs at boot with HLE BIOS (RA).
Issue #1755
2024-11-30 16:37:55 +01:00
Flyinghead b91f82c7e5 win32: create screenshots path if needed. Fall back to Pictures folder
Ask Windows to create the Screenshots folder if it doesn't exist.
Fall back to Pictures folder if the Screenshots folder can't be
determined.
Issue #1761
2024-11-30 13:06:53 +01:00
github-actions[bot] d38ce47081 Fetch translations & Recreate libretro_core_options_intl.h 2024-11-29 22:21:28 +00:00
Flyinghead 5f55a9fd3f naomi: fix issue when creating eeprom. Ignore audio disable.
Byte at offset 2 was incorrect.
Ignore disable attract mode audio in BootID.
Remove ikaruga default eeprom.

Issue #1760
2024-11-29 17:11:36 +01:00
Flyinghead a085fd2f6d ui: never disable Up and Down buttons on iOS. rename source files 2024-11-28 17:45:40 +01:00
Flyinghead 36c2f5137c ios, android: load custom vgamepad image. disable unused controls
User can choose a custom vgamepad image or reset to default.
Unused controls are disabled and hidden based on the game (arcade) or
maple device (console).
2024-11-28 17:09:09 +01:00
Flyinghead 5e9c168fc9 android: add BooleanArray to jni util. refactor using templates 2024-11-28 17:01:39 +01:00
Flyinghead 59c2343cad android: add mime-type argument to addStorage() 2024-11-28 16:46:17 +01:00
Flyinghead b42387e929 naomi: vf4 and mazan input descriptors 2024-11-28 16:41:30 +01:00
Flyinghead df78a781ec allow USE_HOST_LIBCHDR with libretro 2024-11-27 10:04:23 +01:00
Flyinghead 974dc2e233 missing iOS app icon source files
Courtesy of @maxtron95
Issue #1731
2024-11-27 10:02:26 +01:00
Flyinghead 6bf38e5085 input: fix potential race condition with analog ramp up/down
Fix a potential race condition on android causing missed inputs with
analog axes bound to buttons.
2024-11-26 19:29:40 +01:00
Flyinghead 792aa38d34 input: implement ramp up/down for analog axes mapped to buttons
Full analog axes now have a ramp up/down of 100 ms when the mapped
button is pressed/released. Works also for keyboards.
Issue #1017
2024-11-26 16:06:13 +01:00
Flyinghead 516982c66c ios: allow virtual gamepad layout customization
Use same display code as android.
Support custom buttons.png.
Allow layout customization as in android.
Save layout in emu.cfg.
Allow transparency setting.
Issue #990
2024-11-26 10:46:02 +01:00
Flyinghead a9fa33c17a gl: test glBlitFramebuffer compliance and disable its use if failing 2024-11-26 10:03:33 +01:00
Flyinghead d0584b8652 vk: defer deleting framebuffers in ScreenDrawer and lr context
Defer deleting framebuffers and attachments in ScreenDrawer and lr
context when resizing.
Fixes crash when starting 240pSuite on the lr core.
2024-11-23 13:47:19 +01:00
github-actions[bot] 58c8a33d11 Fetch translations & Recreate libretro_core_options_intl.h 2024-11-22 22:20:51 +00:00
Flyinghead b4dcc64ef6 android: draw onscreen gamepad with imgui
Get rid of Renderer::DrawOSD.
gl: make a GlQuadDrawer class.
Draw on-screen gamepad using imgui.
Clean up vgamepad interface.
2024-11-22 14:42:51 +01:00
Stefan Schlosser 7531f5df20 oss: cleanup and unification
Audio and record initializations are unified by providing helper functions for
opening the audio device and for setting the device parameters. The ioctl calls
are properly checked for errors and log an appropriate error message. The init
fails if the requested parameters are not supported by the device, i.e. 44.1kHz
16bit stereo for playback. This provides consistent behavior with all the other
audio backends.
2024-11-22 13:06:18 +01:00
Stefan Schlosser c4d77165a6 lua: add build option for Lua support
The added build option USE_LUA (enabled by default) allows to enable/disable Lua
support in the build. This provides more control over the used dependencies, and
is important especially for OpenBSD and FreeBSD i386 builds, where the build
fails with enabled Lua support, see also [1].

[1] https://github.com/vinniefalco/LuaBridge/issues/302
2024-11-20 18:01:06 +01:00
Flyinghead aa95c71ead libretro build fix 2024-11-20 12:06:39 +01:00
Flyinghead 6612e3fef8 gdrom: update settings and more when swapping disks
Set forced and per game settings.
Update game id and save state file name.
Reset cheats and custom textures.
Update game title and window title.
Issue #1748

hle bios: reboot the game when "exit to bios" vector is called
2024-11-20 11:46:34 +01:00
Flyinghead fbd52a72d4 naomi: load and decrypt gd-rom on demand
Shorten load times and avoid ANR on android with libretro when loading a
GD-ROM game. Load and decrypt data by 16 KB chunk when needed.
Issue #1457
Issue #1738
2024-11-17 20:39:30 +01:00
Flyinghead d618abc320 rend: modifier volumes must be clipped
Modifier volumes should also be clipped when needed.
Implement outside clipping for non-OIT renderers.
OIT renderers are less affected since the shadowed polys themselves are
usually also clipped after shadow is applied.
Fixes overflowing shadows in baserunner cams in WSB 2K1.
2024-11-17 12:09:40 +01:00
github-actions[bot] b7163dda83 Fetch translations & Recreate libretro_core_options_intl.h 2024-11-15 22:21:36 +00:00
Stefan Schlosser d259a2e2f5 libchdr: add build option for using system library
The added build option USE_HOST_LIBCHDR allows to build with libchdr provided by
the system. The option is disabled by default.
2024-11-14 13:17:00 +01:00
Stefan Schlosser e2f8de33e8 audio: add build options for audio backend support
The added build options USE_ALSA, USE_LIBAO, USE_OSS and USE_PULSEAUDIO allow to
enable/disable specific audio backends in the build. This provides more control
over the used dependencies.

The OSS backend wasn't enabled in the previous build configuration, consequently
the build option USE_OSS is set to OFF by default.
2024-11-14 13:16:27 +01:00
vkedwardli 42ad5532b2 Update Xcode project generator (#1732)
* Do not build breakpad in Xcode project, fix `PhaseScriptExecution failed` error and fix Flycast cannot be launched from debugger

* NSLog prettyprint for Xcode 16
2024-11-14 13:15:54 +01:00
Flyinghead 1e30f483c2 New iOS app icon
Courtesy of @maxtron95
Issue #1731
2024-11-14 13:13:59 +01:00
Flyinghead bdd2d5af7f naomi: emulate dimm registers for gd cart
Emulate 1.02 dimm board without network so that the bios detects it and
shows the expected GD-ROM SYSTEM boot screen.
Fix rom board serial id issue (error 04) with ikaruga, tetkiwam,
puyofev[j] and sprtjam.
Issue #1735

Add naomigd and naomidev bios definitions (unused).
Use netdimm for mj1 and wccf* series (still not working).
2024-11-14 13:05:48 +01:00
Flyinghead 76638df001 sh4: split xffr array. Fix FPCB_PAD on windows
Split xffr[32] into xf[16] and fr[16].
Set FPCB_PAD size to 64_KB. Issue #1736
Get rid of shil_param::reg_aofs
2024-11-13 10:31:45 +01:00
Flyinghead 3efb87ba6d vk: fix crash when enabling/disabling EmulateFramebuffer
Make sure to end the current render pass with the previous setting.
Fix initial layout of color attachments in OIT.
Fix missing initial transition after Term/Init in !OIT.
Issue #1734
2024-11-11 22:15:57 +01:00
Flyinghead c9f238362d New macOS app icon
courtesy of @maxtron95
Issue #1731
2024-11-11 22:09:52 +01:00
Flyinghead 129673a84b dynarec: use sh4 ctx to get register pointers. prefer offset
Move restoreHostRoundingMode() into Sh4Context
2024-11-09 18:44:51 +01:00
Flyinghead 7c1c5817d3 sh4: move sqWrite func into sh4 context. Simplify usage
Allow passing sh4 context to dynarec canonical implementations
Reduce FPCB padding to PAGE_SIZE except on arm32
2024-11-09 16:54:47 +01:00
Flyinghead e394840344 sh4: pass sh4 context to dynarecs, sh4cycles and caches
Reorder RuntimeBlockInfo members to save space
2024-11-09 13:25:55 +01:00
Flyinghead fc33002284 network: add Golf Shiyouyo 2 ports 2024-11-09 11:44:58 +01:00
Flyinghead dff967f60a ui: notify user when loading a state fails and why 2024-11-09 11:43:10 +01:00
github-actions[bot] a3708a7e95 Fetch translations & Recreate libretro_core_options_intl.h 2024-11-08 22:20:44 +00:00
Flyinghead 1cadeb276e sh4: test fix 2024-11-08 22:01:48 +01:00
Flyinghead 2b28e819e5 sh4: build fix. rounding mode refactoring 2024-11-08 21:34:24 +01:00
Flyinghead db846ca933 sh4: pass context to interpreter funcs. get rid of sh4 regs #define 2024-11-08 18:36:08 +01:00
Flyinghead 9cb7d9e5d5 rec-arm64: fix Store Queue write handlers 2024-11-08 18:27:52 +01:00
Flyinghead 93ae9d0375 sh4: refactor interpreter and recompiler with Sh4Executor interface 2024-11-07 18:14:18 +01:00
Flyinghead e03e11b8a9 arm64: mask value operand when calling a write mem handler
AppleClang doesn't mask the operand in the callee. This must be done in
the dynarec.
See 6115a918b2
Tentative fix for barcode reader not working on macOS/arm
2024-11-07 14:10:02 +01:00
Flyinghead 52df0133f0 sh4: pass sh4 context to sq write handlers 2024-11-06 23:27:20 +01:00
Flyinghead d5aeb482d9 sh4: move sq_buffer into sh4 context 2024-11-06 22:11:27 +01:00
Flyinghead 7eec648690 sh4: move Sh4RegType & GetRegPtr into sh4/dyna
rec-arm: use getRegOffset/reg_nofs instead of GetRegPtr
2024-11-06 20:46:32 +01:00
Flyinghead 897e06b887 sh4: refactor GetDR/SetDR and access to fp registers 2024-11-06 19:26:04 +01:00
Flyinghead aa38771cd0 refactor sh4_sr_GetFull/sh4_sr_SetFull 2024-11-06 18:01:01 +01:00
Flyinghead c77ddba109 get rid of settings.dynarec.disable_nvmem 2024-11-06 17:03:01 +01:00
Flyinghead cd8a88366d get rid of TARGET_NO_EXCEPTIONS 2024-11-06 16:59:16 +01:00
Bobby Smith f892630e4b [Libretro] Add game dir as fall back for arcade BIOSes 2024-11-06 16:46:29 +01:00
Flyinghead 9d4d486524 naomi: add crc32 to GDROM and AW roms 2024-11-06 16:45:42 +01:00
Flyinghead d8a3ee9c3a android: disable openmp affinity on some devices
Disable omp affinity on POCO F5, Redmi Note 12 Turbo, Redmi Note 13 Pro
5G and POCO X6 5G to avoid crashes.
2024-11-06 16:40:11 +01:00
Flyinghead fc6142b332 maple: do a full save of the vmu after loading a state
A partial save might corrupt the vmu file system.
2024-11-04 19:19:31 +01:00
Flyinghead 5fc84acdfb maple: base vmu file name on game ID for multidisk games
Build vmu file name with game ID so that all disks of multidisk games
share the same vmu (A1 only, or all with libretro when enabled).
Rename existing vmu file to new format if none exists.
Issue #1556
2024-11-03 17:14:31 +01:00
Flyinghead 037dc3b4b9 atomiswave: set dma speed to 7 MB/s for all aw games and conversions
AW dma transfer rate seems to be lower than naomi.
Fixes Force Five freeze when starting a game.
Fixes opening sequence animation being truncated in kofxi.
Issue #1724
2024-11-03 16:55:15 +01:00
Flyinghead 96aac66133 naomi: improve performance of M1 and M4 carts dma
Limit buffer size to 1 or 2 KB instead of 32 KB.
Only decrypt right before dma transfer.
Fixes frame drops and audio underruns in vf4evoct attract mode.
Issue #1717
2024-11-02 18:46:49 +01:00
Flyinghead 4d5ced1ce6 maple: add Full Controller with 2 analog sticks and all buttons
add AllStatusReq string for purupuru device.

Issue #1171
2024-11-02 18:13:38 +01:00
scribam da3cfd9d58 deps: update sdl to version 2.30.9 2024-11-02 11:05:35 +01:00
Flyinghead 65aadb9dcb pvr: avoid infinite loop if tile array is invalid
Fixes 240pSuite freeze at boot with the libretro core.
2024-11-02 11:04:56 +01:00
github-actions[bot] cec46990ea Fetch translations & Recreate libretro_core_options_intl.h 2024-11-01 22:21:16 +00:00
Flyinghead 2e5309bfa3 aica: don't batch samples
Batching 32 samples and arm runs causes audio glitches with some wince
games. So run aica 44100 times/sec instead.
Issue #1240
Issue #1605
2024-11-01 14:31:59 +01:00
Flyinghead 742090bb1f rcheevos: disable achievements in naomi slaves 2024-10-29 17:38:52 +01:00
Flyinghead f3a64e5891 android: clean exit when using the exit hotkey
Finish the activity in dc_exit.
Issue #1713
2024-10-29 17:35:25 +01:00
Flyinghead 32ccb754ff libretro: fix translations
Issue #1688
2024-10-29 15:39:17 +01:00
Alexandre Bouvier 32d11dd89c fix missing include 2024-10-26 19:28:20 +02:00
github-actions[bot] 760813e45a Fetch translations & Recreate libretro_core_options_intl.h 2024-10-25 22:20:46 +00:00
Flyinghead e221f6fed2 deadlock when pausing/resuming quickly (android)
Race condition when pausing/resuming is done from a separate thread (android): the renderer gets a result ready status for the previous emu thread, but waits on the newly created one forever.
2024-10-25 08:10:41 +02:00
Flyinghead 8108e63907 rcheevos: race condition in event handlers and async tasks
The data passed to event handlers (achievements in particular) must be
copied if used by an async task. It might be deleted before the async
task runs.
Fixes MINIDUMP-3ZR MINIDUMP-4XJ MINIDUMP-4TB MINIDUMP-4CA MINIDUMP-38H
2024-10-21 16:13:00 +02:00
Flyinghead b0403ed103 imgui: ignore invalid fonts when merging
Avoid crashing in release mode if a merged font is invalid or FontNo
can't be found. The font is simply ignored and the glyph range isn't
loaded.
Fixes MINIDUMP-4TD
2024-10-21 16:03:28 +02:00
Flyinghead c86ed291cf picotcp: use dns.flyca.st as default dns
Use dns.flyca.st as default dns.
Resolve name when pico network starts.
2024-10-19 17:59:24 +02:00
Flyinghead d981c48a75 libretro: fix translations 2024-10-19 12:47:26 +02:00
github-actions[bot] 82925c4e81 Fetch translations & Recreate libretro_core_options_intl.h 2024-10-18 22:20:39 +00:00
Flyinghead 54e8589f63 android: disable import/export home when SAF is disabled. Code clean up
Disable import/export home folder buttons when not using SAF file
picker.
Get rid of unused home migration feature when onboarding.
Android TV screenshots and banner.
2024-10-18 19:23:03 +02:00
Flyinghead 4750ddb646 android: new option to use legacy file picker instead of new SAF one
Android 9 and earlier can use the legacy file browser. This fixes issues
with broken SAF file picker on Android TV 9.
Catch exception when no file picker is installed on the device (Android
TV 12) and instruct the user to install one.
Issue #1657
2024-10-17 16:21:06 +02:00
Flyinghead 894ac54b80 imgui: fix dpad navigation issue on shield tv
Pressing dpad up or down moves the selection 2 lines up or down resp.
Regression due to ca613db70d.
Happens on 1920x1080 screen with 213 dpi.
Relax vertically touching items test.
2024-10-17 16:04:27 +02:00
Flyinghead d4a223656f enable RTT Copy to VRAM for Silent Scope
Fixes VMU display
Issue #1703
2024-10-17 16:00:46 +02:00
Flyinghead b698cc3d10 dx11: reset device context state to fix libretro shaders
Reset device context before each render. Rebind palette and fog textures
every frame.
Fixes corruption with libretro shaders.
Issue #1612
2024-10-15 17:28:54 +02:00
Flyinghead 75af269bb8 rend: ignore inside clipping if rect is default value
Fixes invisible race start countdown in f355 (arcade).
Issue #1698
2024-10-15 15:55:34 +02:00
Flyinghead fd475bdd8e vk: some pipelines don't need the provoking vertex extension
ModVol and OIT Final and Clear pipelines don't need it.
2024-10-14 17:19:41 +02:00
Flyinghead f71dd6d4d8 cdi: better detection of invalid CDI media 2024-10-14 16:45:22 +02:00
Flyinghead 5aec6d05b0 vk: (lr) use one vk::DeviceQueueCreateInfo when possible
Using 2 with the same queue index causes a validation error and crash.
2024-10-14 16:39:33 +02:00
Flyinghead b4937ef271 f355: pass full BIOS path to slaves
if the bios file is located relative to the rom location, slaves won't
be able to find it. Pass the full bios path to avoid the issue.
2024-10-14 16:31:23 +02:00
Flyinghead a50164a91b vk: missing some changes to use VK_FORMAT_R8G8B8A8_UNORM
Fixes Naomi 2 games and android on-screen gamepad.
2024-10-13 14:22:50 +02:00
Wunkolo 595842f606 vk: Remove naomi2 vertex attributes when not needed
Disables the naomi2 vertex input attribute when emitting non-naomi2 pipelines.
This addresses some validation messages involving unused vertex inputs and optimizes the bandwidth of the input assembler a little bit for non-naomi2 games.
2024-10-13 13:26:42 +02:00
Wunkolo 8f74f7883a vk: Use VK_FORMAT_R8G8B8A8_UNORM for vertex colors
Rather than using `VK_FORMAT_R8G8B8A8_UINT` for these vertex attributes and then dividing by `255.0` in each of the shaders, the `VK_FORMAT_R8G8B8A8_UNORM` format will automatically remap byte components into the `0.0-1.0` range and removes the need to do the extra divisions or castings within the shader.
2024-10-13 13:25:40 +02:00
scribam 71dc4c3e39 ci: disable android signing on pull requests 2024-10-13 13:25:02 +02:00
scribam 6edad8eaba android: update gradle and agp 2024-10-13 13:25:02 +02:00
Wunkolo ea1cd9d31b vk: Fix undefined push-constant data
The full push-constant region is 24 bytes(6 floats), but some of these push-constant writes only wrote 20 bytes of data(5 floats).
Causing 4 bytes at the end to be left undefined.
Resolved by pushing an extra zero.
2024-10-13 13:24:27 +02:00
Flyinghead bb7ad07701 extra depth scale for sturmwind
Issue #1691
2024-10-12 17:35:59 +02:00
Flyinghead 9793e54646 avoid deadlock when sh4 cpu is restarted while emu is being stopped
The sh4 cpu is stopped/restarted during a soft reset, and dynarec code
reset (arm64, arm, x86). If the emulator is stopped concurrently, the
call may hang. Use a mutex-protected method to restart the cpu only if
the emu is still running.
2024-10-12 17:31:58 +02:00
Flyinghead 6d2ed417be lr: fix core options to work around translation issue
Adjacent string literals aren't supported.
Fix syntax errors in libretro_core_options_intl.h
Issue #1688
2024-10-12 11:49:12 +02:00
github-actions[bot] d3916f13d7 Fetch translations & Recreate libretro_core_options_intl.h 2024-10-11 22:20:30 +00:00
Flyinghead b2c6159b10 Merge remote-tracking branch 'origin/dev' 2024-10-11 15:28:19 +02:00
Wunk 4d73cc8e13 vk: Add VK_EXT_provoking_vertex optimization (#1681)
* vk: Add `VK_EXT_provoking_vertex` optimization

The dreamcast uses the last vertex as the provoking vertex, while vulkan uses the first vertex.
This requires an additional call to `setFirstProvokingVertex` to reorder the vertices for all incoming geometry.
With `VK_EXT_provoking_vertex`, the pipeline can designate that the provoking vertex is to be the last vertex, which removes the need to re-order incoming geometry on the CPU.

* vk: Propagate physical device API version to VMA

Allows VMA to make assumptions such as using the `*KHR` or non-`KHR` versions of certain function names.

* vk: Refactor libretro device initialization for `VK_EXT_provoking_vertex`

* vk: Top out at vulkan API version to VMA to 1.1

Despite the physical device possibly being 1.2 or 1.3, we only want up to 1.1. Otherwise we will be responsible for other API functions being resolved and loaded when passing to VMA.

* vk: Enable `VK_EXT_provoking_vertex` usage for ModVol and Final(OIT) pipeline

* vk: Enable `VK_EXT_provoking_vertex` for ModVol(OIT) pipeline

Pretty much anything handling dreamcast-geometry should use this extension when available

* vk: Additional `VK_EXT_provoking_vertex` pipeline fixes
2024-10-11 10:23:48 +02:00
Wunkolo 5b343562b9 vk: Add CommandBufferDebugScope utility-type
Adds a new RAII-based utility type for adding diagnostic information to command buffers.
Enabled only when `VK_DEBUG` is set to `1`.
2024-10-09 19:47:14 +02:00
Wunkandflyinghead b20db6a8bb vk: Disable LOD clamping in samplers (#1674)
This addresses the `BestPractices-Arm-vkCreateSampler-lod-clamping` message from ARM:
https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/65b79bac615ec1c47ab61a02d55a3bba871b56b9/layers/best_practices/bp_descriptor.cpp#L103-L110

Rather than clamping the LOD in the samplers, instead rely on the Image-View's `vk::ImageSubresourceRange` to limit the number of sampled LODs.

Currently, only game-textures actually have MipMaps, so this does not introduce any additional mip-map sampling or filtering anywhere. If any code want's to actually limit the number of LODs sampled, then they would allocate an additional ImageView for the range of MipMaps to be sampled.

Co-authored-by: flyinghead <[email protected]>
2024-10-09 19:46:36 +02:00
Wunkolo a8bc1c12f4 vk: Optimize redundant QuadBuffer uploads
Hashes the contents of the `QuadBuffer` vertex-data such that data is only uploaded when the vertices actually change rather than every frame.
2024-10-09 19:40:59 +02:00
Wunkolo b94acb70a6 vk: Use matching u/v/w sampler address-mode when possible
This addresses the `BestPractices-Arm-vkCreateSampler-different-wrapping-modes` message from ARM:
https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/65b79bac615ec1c47ab61a02d55a3bba871b56b9/layers/best_practices/bp_descriptor.cpp#L95-L100

The `W`-axis for these samplers is always unused, it's never the case that these samplers are going to be used for 3D textures.
ARM suggests trying to keep all of the wrapping-modes the same if possible for performance.

`wRepeat` will be set to the same value as `vRepeat` to try and encourage all three wrapping-modes to be the same.
2024-10-09 19:40:20 +02:00
Wunkolo 0c3f5c7a76 vk: Refactor device/instance extension enablement
* Uses a utility-lambda for repeated extension-adding logic
* Uses an `std::set` for the list of available extensions for quick queries
* `VK_EXT_DEBUG_REPORT` and `VK_EXT_DEBUG_UTILS` aren't device extensions and don't need to be here. They are instance extensions
* Each extension that is tested to be added has a corresponding log message for if it was enabled or if it was unavailable

```
00:00:162 rend\vulkan\vulkan_context.cpp:427 N[RENDERER]: Device extension enabled: VK_KHR_swapchain
00:00:162 rend\vulkan\vulkan_context.cpp:427 N[RENDERER]: Device extension enabled: VK_KHR_get_memory_requirements2
00:00:162 rend\vulkan\vulkan_context.cpp:427 N[RENDERER]: Device extension enabled: VK_KHR_dedicated_allocation
00:00:162 rend\vulkan\vulkan_context.cpp:430 N[RENDERER]: Device extension unavailable: VK_KHR_portability_subset
00:00:162 rend\vulkan\vulkan_context.cpp:430 N[RENDERER]: Device extension unavailable: VK_EXT_debug_marker
```
2024-10-09 19:39:49 +02:00
Flyinghead 03d20f9d5a bug report: ask for flycast version instead of github hash 2024-10-09 19:39:04 +02:00
Flyinghead 01e5cd882c pvr: fix default clipping rectangle
Set default clipping rectangle to max (1280x480).
Fixes Irides: Master of blocks bogus clipping to tile 0,0.
2024-10-09 19:37:42 +02:00
Wunk 556e2ead56 vk: Refactor physical device selection (#1671)
Rather than electing the first physical device it finds, and falling back on the first-listed GPU: a series of stable-partitions are done so that the "least compromising" GPU is selected based on a series of criteria.

It will now maximally try to find a GPU that(in order of priority):
* Is a discrete GPU
* Supports `fragmentStoresAndAtomics`
* Supports `R5G5B5`/`R5G6B5A1`/`R4G4B4A4`

In the case that a system has two dGPUs and one of them supports optimal-formats, the optimal-format one is selected

In the case that a system has an iGPU and the dGPU and they both support optimal formats, the dGPU is selected.

In the case that a system has an iGPU and the dGPU and the dGPU doesn't support optimal formats, the dGPU is still selected.
2024-10-08 17:07:09 +02:00
Wunkolo ff6a3119b0 vk: Determine object type enum when setting object name
Uses compile-time type-information provided by vulkan-hpp to automatically determine a vulkan-object's `objectType` when calling `setObjectName`.
2024-10-08 17:05:32 +02:00
Wunkolo 86657c0c12 Fix {Push,Pop}StyleVar assert
When entering an error or contentpath warning popup, there are two `ImguiStyleVar` on the stack.
Within the pop-up frame, an additional `ImguiStyleVar` is added.
When the popup ends, there is technically one more ImguiStyleVar on the internal stack than when we entered the popup, causing an assert to hit:

```
Program: G:\flycast\out\build\x64-Debug\flycast.exe
File: G:\flycast\core\deps\imgui\imgui.cpp
Line: 10104

Expression: SizeOfStyleVarStack >= g.StyleVarStack.Size && "PushStyleVar/PopStyleVar Mismatch!"
```

These nested imgui RAII objects need to be scoped such that the stack is preserved both upon entry and exit of these popups to avoid these asserts.
2024-10-08 17:05:03 +02:00
Flyinghead d7c168f406 naomi: copy cart dma data in chunks
Copy cart dma data in 1K chunks to avoid transferring all in one shot.
Fixes Soul Surfer and Beach Spiker audio glitches when playing a sample
before it's completely transferred.
Issue #1513
2024-10-08 17:03:00 +02:00
Flyinghead f37e43b26f vk: don't set scissoring in final OIT subpass
If scissoring is enabled, previous framebuffer background isn't drawn
outside of scissor region.
Fixes blinking in Soul Calibur battle loading screen.
Issue #1668
2024-10-08 11:49:34 +02:00
Flyinghead e427c4d5c4 lr: don't set IntOption if overridden
Fixes OIT Max Layers overrides being ignored.
Issue #1610
2024-10-08 11:39:49 +02:00
Wunkolo 56fe3b9c9d Fix arm64_unwind.h include-order
`sh4_core.h` has defines for symbols like `r` and `pr` which conflict with the variable names in `arm64_unwind.h` and cause even deeper errors over in `wingdi.h(4954)` and `wincrypt.h(4741)`.

Swapping the include order avoids this collision.
2024-10-07 18:48:26 +02:00
Flyinghead 30bb864b37 vulkan: check image usage flags if image already exists during RTT
Recreate image if usage flags are incorrect.
Fixes vk validation error in Virtua Tennis player list selection screen.
Issue #1664
2024-10-07 18:47:52 +02:00
nbFlyinghead d689c50e21 naomi: increase dma xfer rate except for force five
Revert 54ac9c6361 but make an exception
for force five. Issue #141
Fixes loud music in beach spikers and soul surfers. Issue #1513
Fixes some menu textures not being loaded in F355.
2024-10-05 13:30:36 +02:00
Flyinghead efd71b3a44 Storage::getParentPath can throw 2024-10-04 16:51:08 +02:00
Flyinghead 5450646b5c android: add virtual gamepad transparency setting
Issue #384
2024-10-04 16:45:28 +02:00
Flyinghead 55e0211a57 android: use ASS to select custom adreno driver 2024-10-04 16:36:56 +02:00
Flyinghead 5d719e0b49 rend: unexpected conversion to unsigned for VO_STARTX/Y with msvc
MSVC converts VO_STARTX and VO_STARTY bit-field values to unsigned int,
leading to an overflow when the result is negative.
Issue #1606
2024-10-03 18:03:55 +02:00
Flyinghead e10a9929da Set OIT max layers for more games
Issue #1610
2024-10-03 17:56:30 +02:00
scribam 3d41e4ea3e deps: update sdl to version 2.30.8 2024-10-02 19:50:37 +02:00
Flyinghead 2dd4cbe33d vk oit: draw transparent polys in the first frame after (re)init
Fixes missing background in progress window in Fighting Force 2
Issue #1652
2024-09-29 16:42:38 +02:00
Flyinghead 2653c5ed73 naomi2: fix modifier volumes clipping
Don't clip modifier volumes but tesselate triangles intersecting the
near plane. Then project clipped vertices onto it in the vertex shader.
Issue #1651
2024-09-29 16:42:38 +02:00
github-actions[bot] 343021a8c5 Fetch translations & Recreate libretro_core_options_intl.h 2024-09-27 22:20:38 +00:00
flyinghead 7907100b9c dx11: wrong texture returned to libretro in some cases
If a render to texture happens before presenting the current frame,
another texture will be bound to shader slot #0 and will be returned to
the libretro frontend.
Issue #1616 and #1619
2024-09-25 21:57:15 +02:00
Flyinghead f179c00bdd gl: fix Delay Frame Swapping pacing issue on android
Partial revert of c83b0e325f.
Fix root issue in OpenGLRenderer::DrawOSD.
2024-09-24 14:50:41 +02:00
Flyinghead c83b0e325f android: fix Delay Frame Swapping sync issue. ANR in single-threaded
Framebuffer swap should only be called when a new frame has been
rendered.
ANR when stopping the emulator in single-threaded mode: race condition
causes stopRequested to not be handled, and Pause event is never sent.
2024-09-24 11:54:15 +02:00
Flyinghead 210e8ca6e3 android: get rid of ouya sdk 2024-09-23 20:46:33 +02:00
Flyinghead a46dc71156 android: target android 14 / sdk 34 2024-09-23 18:01:21 +02:00
Flyinghead 4baf529ff7 race condition when stopping emu thread right after start
In threaded rendering, CpuRunning is set after the emu thread is
started. If calling Emulator::stop() before it is set, the call will
hang.
2024-09-23 17:43:23 +02:00
Flyinghead 63ef3aaab4 android: avoid crash when app is run in restricted mode
App may be run in restricted mode, where the Application object is a
generic android.app.Application. Disallow backup to avoid this. If
Application object isn't of the expected type, restart the app.
2024-09-23 17:21:02 +02:00
Flyinghead abe71409b5 android: race condition with render thread. ANR with auto save state
Race condition when starting then stopping the render thread:
mainui_enabled isn't set until after the thread has started. If stopped
during that time, it will hang.
Auto save state in a background thread to avoid ANR.
2024-09-23 17:17:46 +02:00
Flyinghead f8c12d2835 android: fix getFileInfo for document uri. cheats: limit file size
android: Fix AndroidStorage.getFileInfo for document uri (cheat file)
cheats: limit cheat file size to 1MB to avoid parsing garbage forever. Save file path only if valid.
2024-09-23 17:08:57 +02:00
github-actions[bot] 92555c68c6 Fetch translations & Recreate libretro_core_options_intl.h 2024-09-20 22:20:53 +00:00
Flyinghead 915532f946 vk: don't depend on current clamping values when compiling shader
Fog clamping values may change so the shader shouldn't depend on the
current value when compiling.
Fixes Red Dog Superior Firepower glitch.
Issue #1642
2024-09-18 11:34:35 +02:00
Flyinghead 079180faab Force PAL for Snow Surfer. Increase Max Layers for some games.
Force PAL broadcast for Snow Surfer.
Issue #1643
Increase max layers for Soldier of Fortune, BANG! Gunship Elite and MDK
2.
Issue #1610
2024-09-18 11:30:46 +02:00
Flyinghead 38de2868a0 sgdrvsim: axis 0 is master audio volume, not wheel
Use (unused) axis 4 instead. Wheel position is read with the ffb drive
board, not JVS.
Map clutch to left trigger 2.
Issue #1636
2024-09-16 18:26:13 +02:00
Flyinghead 0e97f97bb7 android: virtual gamepad rumble power wasn't set at app startup
Make sure emu.cfg is loaded before setting rumble power.
Issue #1640
2024-09-16 11:28:25 +02:00
Flyinghead 64d7199107 Merge remote-tracking branch 'origin/master' into dev 2024-09-16 11:16:04 +02:00
scribam 0077b8ecec deps: update sdl to version 2.30.7 2024-09-08 16:24:37 +02:00
Flyinghead 5393235c40 aica: skip remaining step functions when channel is disabled
CA is reset to 0 when channel is disabled due to AEG and this value must
not be changed.
Issue #472 and #1180
2024-09-07 14:55:45 +02:00
Flyinghead a81a02f14b maple: save rfid card after decrementing counter
Issue #1626
2024-09-07 14:50:29 +02:00
github-actions[bot] 480f93e50d Fetch translations & Recreate libretro_core_options_intl.h 2024-09-06 22:21:05 +00:00
Flyinghead 7174ef1194 naomi: full rfid chip emulation for mushiking series
Fixes hang after playing 3 games.
Issue #1626
2024-09-04 09:48:34 +02:00
Flyinghead f039a809da naomi: limit max analog values to avoid overflow
Fixes overflow in wild riders when going full right or full accel/brake.
Follow up to Issue #1627
2024-09-02 17:04:17 +02:00
Flyinghead 1223154665 jvs: fix analog axes values encoding
The least significant byte of analog axis values seems to be handled as
signed.
Fixes crazy taxi going right when turning full left.
Issue #1627
2024-09-01 18:41:37 +02:00
Flyinghead 8cb847940b vk oit: attachment 0 must be loaded too
Issue #1614
2024-09-01 18:41:37 +02:00
github-actions[bot] 9691fe9622 Fetch translations & Recreate libretro_core_options_intl.h 2024-08-30 22:20:34 +00:00
Flyinghead c575eac89b naomi: add mushik4t rom 2024-08-30 17:49:07 +02:00
Flyinghead b468c9bdae aica: reset CA to 0 when disabling channel due to AEG
CA was reset to 0 for non-looping sound when ending, but not for looping
ones when they reach full attenuation. This confuses some games.
Disable the channel when it reaches full attenuation and reset CA to 0.
Revert a7702c622a
Issue #1602
Better fix for
Issues #472, #483, #1180, #1249, #1030 (partial)
2024-08-29 13:09:39 +02:00
Flyinghead 368bd17ae0 vk: use swap_chain_size + 1 semaphores
Fixes validation error VUID-vkAcquireNextImageKHR-semaphore-01779
introduced in vulkan sdk 1.3.275
Issue #1620
2024-08-29 13:01:11 +02:00
Flyinghead 757732d0f8 vk oit: load correct attachment. Only reset pipelines when needed
Fixes partial renders: ECCO initial sequence.
Issue #1614
Don't reset pipelines when resizing framebuffer.
2024-08-29 12:57:10 +02:00
Flyinghead 0ff9caf656 ci: make breakpad optional on all platforms
Issue #739
2024-08-29 12:06:29 +02:00
Flyinghead a93bd9e64e Merge remote-tracking branch 'origin/playstore' into dev 2024-08-24 18:08:59 +02:00
Flyinghead 308d9fc1ac Increase max transparent layers for some games
Issue #1604
Add 96 layers option to libretro core.
Issue #1610
2024-08-24 16:49:16 +02:00
Flyinghead 7a27a43ba4 vulkan: Fix multipass RTT in OIT mode
Use correct temp attachment depending on pass count. Keep attachment
index to bind the correct one before final subpass.
Use correct initial layout for OP+PT attachment 1 (was eUndefined) when
creating the RTT render pass.
Fixes Alone in the Dark cutscenes.
Issue #1609

Recreate RTT attachments if switching CopyToVRAM on/off.
2024-08-24 16:37:52 +02:00
Flyinghead 244bb724c9 naomi: add FFB support for Tokyo Bus Guide
Only rumble seems to be used.
Issue #1601

Add info about awave BIOS
2024-08-24 16:29:29 +02:00
github-actions[bot] 349083030d Fetch translations & Recreate libretro_core_options_intl.h 2024-08-23 22:20:21 +00:00
Flyinghead b99b3450c8 sh4: compute fsrra as 1/sqrt(x) instead of sqrt(1/x)
Fixes invisible chaos emerald in Sonic Adventure cutscene after Emerald
Coast.
Partial revert of ec3ad9b.
Issue #1600
2024-08-20 21:12:05 +02:00
Flyinghead 6061d402bd build fix 2024-08-17 18:08:53 +02:00
Flyinghead 4d06743d9a gdrom: don't crash on unsupported sector size
Fixes MINIDUMP-284
2024-08-17 17:56:35 +02:00
Flyinghead af7353225b pvr: rgb888 needs to be correctly aligned when xclip.min != 0
Fixes glitchy combat opening animation in soul calibur (with full
framebuffer emulation). Use slower but correct method instead.
Issue #1591
2024-08-17 17:29:32 +02:00
Flyinghead cb0b667129 maple: don't assert dma interrupt if using hardware dma trigger
Fixes Virtua Cop 2 pause when shooting. Regression due to ecce915
Issue #474
2024-08-17 17:23:34 +02:00
Flyinghead 00f60a3d62 win32: don't compile clock.c with clang
Issue #1588
2024-08-17 17:08:40 +02:00
github-actions[bot] 5565b79b9e Fetch translations & Recreate libretro_core_options_intl.h 2024-08-16 22:20:19 +00:00
Flyinghead 8ea12443d3 android: fix touchscreen coords when view is scaled
Samsung phones/tablets can scale down the emulator view to improve
performance. In this case, getPointerCoords() returns screen, not view
coordinates. Use MotionEvent.getX/Y() instead.
2024-08-16 13:12:27 +02:00
Flyinghead 6679cb2f31 android: show/hide keyboard in main thread to avoid deadlock
Tentative fix for deadlock when main thread is calling
JNIdc.rendinitNative(null), and render thread is blocked on a lock
trying to hide on-screen keyboard.
2024-08-16 10:17:06 +02:00
Flyinghead f1fd8b12e2 android: do all rumble/haptic on background thread
Haptic effects for the virtual gamepad must be done on a background
thread. Not sure about gamepad rumble but it shouldn't hurt.
Reuse haptic duration for haptic power (0-100).
Fix crash when power is zero (createOneShot needs power >= 1)
2024-08-15 17:25:02 +02:00
Flyinghead ecb468a723 msvc build fix 2024-08-15 13:05:02 +02:00
Flyinghead fbe7cc8fe3 input: crash when setting the keyboard to port None
Issue #1593
2024-08-15 12:28:22 +02:00
Flyinghead aafa9f0bf0 android: intent url ignored unless external storage legacy is enabled
Issue #1584

Accept fileDir (internal storage) as home folder in case it was created
without external storage.
2024-08-15 12:09:27 +02:00
Flyinghead dae3676979 android: NPE in NativeGLView when Emulator.currentActivity is null 2024-08-15 11:58:45 +02:00
Flyinghead 09ab139407 android: deadlock when Emulator::checkStatus is called concurrently
If checkStatus(wait = true) is called, any other thread will be blocked
even when calling with wait = false since the mutex is locked. This
happens on Android when JNIdc.rendinitNative(null) is called by the app
main thread.
Use a shared_future instead and unlock the mutex before waiting.
2024-08-15 11:55:07 +02:00
Flyinghead 138adc28d7 android: ANR when loading cheat file 2024-08-13 17:41:40 +02:00
Flyinghead 9fd80b952a Storage::getSubPath can throw if path doesn't exist (android) 2024-08-13 17:38:23 +02:00
Flyinghead a058481e36 oboe: log record stream buffer capacity, not output stream
Fixes MINIDUMP-43E
2024-08-13 17:18:31 +02:00
scribam 45bf218df4 ci: bump actions/setup-python to v5 2024-07-29 16:45:12 +02:00
scribam 6b3e86619e deps: fix libzip compilation error with gcc 14.1 2024-07-28 20:02:34 +02:00
scribam 56b8bb1245 vk: cleanup
* Use constants for extension names
* Prefer VK_USE_PLATFORM_* constants
* Remove IOS_MVK/MACOS_MVK deprecated code
2024-07-28 20:02:34 +02:00
scribam cea80560db deps: update submodules
* discord-rpc: use upstream repository
* googletest: v1.15.0
* libchdr: master
* oboe: v1.9.0
* rcheevos: v11.5.0
2024-07-28 20:02:34 +02:00
scribam 088c1e6b0d unit: build fix for apple platform when ctest is enabled 2024-07-28 20:02:34 +02:00
scribam bb048dea8f ci: use default xcode version
Currently, it is Xcode 15.4
2024-07-28 20:02:34 +02:00
scribam 588dca2bfd cmake: cleanup
* Set min macos deployment version to 10.13. This is the lowest version supported by Xcode 14.3.1 and 15+
* Prefer target_compile_options to add compilation flags
* Simplify macos custom commands with TARGET_FILE and TARGET_FILE_DIR
* Do not install discord-rpc and libzip files
2024-07-28 20:02:34 +02:00
github-actions[bot] 3afa4322f1 Fetch translations & Recreate libretro_core_options_intl.h 2024-07-26 22:20:39 +00:00
Flyinghead 33d1dafdb7 android: revert changesNotSentForReview param change
Probably due to the current weather conditions at google's HQ
2024-07-20 10:58:26 +02:00
Flyinghead 8b2c1bc5dc android: bug fixes
onInputDeviceAdded may be called with an invalid device id. Avoid NPE
onGenericMotionEvent: event may have a null device. Avoid NPE
getExternalFilesDir may return null if no external storage available.
Use getFilesDir in this case.
Catch exceptions in HomeMover and continue.
addStorage: catch SecurityException and alert user. Graceful failure.
2024-07-20 10:30:27 +02:00
Flyinghead 2b83df86cd boxart: don't save database when pausing (android, uwp)
Avoids ANR on android. Unnecessary since database is now saved
regularly.
2024-07-20 10:07:18 +02:00
github-actions[bot] 0b6b8b3753 Fetch translations & Recreate libretro_core_options_intl.h 2024-07-19 22:21:06 +00:00
Flyinghead 53d092c326 naomi: set SB_GDSTARD and SB_GDLEND when starting dma
Fixes toukon4 fmv freeze
Issue #1582
2024-07-17 10:05:58 +02:00
flyinghead bfba850ee7 Google Play install link 2024-07-16 09:49:29 +02:00
scribam db5a4d1247 ci: add lua54 for freebsd and netbsd 2024-07-14 10:32:33 +02:00
scribam 3ad00596a1 ci: use freebsd 14.1 2024-07-14 10:32:33 +02:00
Flyinghead 39e04b07b8 Merge remote-tracking branch 'origin/dev' 2024-07-11 18:27:44 +02:00
Flyinghead b9cbf3e47f lr: get rid of trash 2024-07-11 18:27:31 +02:00
Flyinghead 72d9ad34dc google play: don't send changes for review automatically 2024-07-08 17:15:42 +02:00
Flyinghead e72a867363 ui: only show dreamcast bios entry if bios present 2024-07-08 16:49:20 +02:00
scribam 2a4356e72c deps: update sdl to version 2.30.5 2024-07-06 14:04:24 +02:00
Flyinghead 136ce267dc aica: apply 6dB attenuation after adding channels in mono
Less saturation with sega bass fishing challenge's default audio
settings.
Issue #1564
2024-07-06 14:03:48 +02:00
github-actions[bot] c6f50fad9d Fetch translations & Recreate libretro_core_options_intl.h 2024-07-05 22:20:32 +00:00
Flyinghead 916afeb5ef Fix Cool Boarders Burrrn game id
Issue #1073
Issue #1265
2024-07-04 09:00:30 +02:00
Flyinghead 81842ccc23 Cool Boarders Burrn and Castle Fantasia fixes
Force HLE Bios for Cool Boarders Burrn.
Issue #1073
Force Copy to VRAM for Cool Boarders Burrn and Castle Fantasia.
Issue #1265
2024-07-03 17:38:23 +02:00
Flyinghead 4fdd28fab7 rend: intersect poly clipping with base clipping
Fixes glitch in FluffMatch split-screen (Fur Fighters)
Issue #145
2024-07-03 11:13:51 +02:00
Flyinghead a01edd22c7 Merge remote-tracking branch 'origin/dev' into playstore 2024-06-30 11:24:46 +02:00
Edward Li c1f5f2e8f9 Do the conversion in Oboe to try to get a low latency stream 2024-06-30 10:36:44 +02:00
scribam f6c1503887 deps: update sdl to version 2.30.4 2024-06-25 14:02:58 +02:00
scribam 71982eda7a miniupnp: add support for api version 18 2024-06-25 14:02:31 +02:00
Flyinghead fefdb6c661 Merge remote-tracking branch 'origin/master' into dev 2024-06-23 16:15:13 +02:00
Flyinghead 4dd490034a android: disable home folder migration 2024-06-23 16:13:28 +02:00
Flyinghead 719fd70860 sdl: always open haptic interface. use default rumble except for wheels
Always open joysticks haptic interface if available and create FFB
effects if supported.
Use default joystick rumble except for racing wheels (sine effect)
Revert 4e3d1caf3f
2024-06-23 16:06:50 +02:00
Flyinghead 49ad2b6864 naomi: save printer output as a screenshot
Use hostfs::saveScreenshot()
2024-06-23 16:00:31 +02:00
scribam 7d645541f8 ci: remove brew zstd 2024-06-23 11:15:34 +02:00
Flyinghead f50d6204dd android: tentative fix for touchscreen not working on android 14
Use more generic source test to detect touch events. Also get rid of
Retroid Pocket 2+ specific test.
Issue #1421
2024-06-23 11:05:40 +02:00
Flyinghead e270621a03 f355: fix gearbox and clutch mappings 2024-06-22 21:40:07 +02:00
Flyinghead 07172416c1 android: tentative fix for touchscreen not working on android 14
Use more generic source test to detect touch events. Also get rid of
Retroid Pocket 2+ specific test.
Issue #1421
2024-06-22 15:07:05 +02:00
github-actions[bot] f9dcd08cf3 Fetch translations & Recreate libretro_core_options_intl.h 2024-06-21 22:20:38 +00:00
Flyinghead 83a27b9125 android: import/export home folder
Use "folder" instead of "directory" in UI.
When game list is empty, show button to easily add a new content path.
Improve folder paths display in settings with middle ellipsis.
android: import/export home folder content
2024-06-21 18:37:34 +02:00
Flyinghead 9976fe10fb android: gamepad rumble support (untested)
Use single thread to handle rumble for virtual and physical gamepads.
Use heavy click effect for vgamepad buttons when available (android 10)
Handle rumble inclination param.
2024-06-21 18:32:25 +02:00
Flyinghead af7edadedb Merge remote-tracking branch 'origin/dev' into playstore 2024-06-21 18:20:40 +02:00
Flyinghead d882c48b4f android screenshots 2024-06-20 18:18:01 +02:00
Flyinghead d92790e69f sh4: incorrect div1 implementation if Rn == Rm 2024-06-20 18:12:11 +02:00
Flyinghead 5eef0309bf Merge remote-tracking branch 'origin/master' into dev 2024-06-20 18:02:36 +02:00
Flyinghead 5f88293fbd discord-rpc: disable clang-format 2024-06-19 15:08:09 +02:00
Flyinghead 245b9043c5 gl: GL_READ_FRAMEBUFFER doesn't exist in GLES2
and glBindFramebuffer isn't needed at this point
2024-06-19 15:06:13 +02:00
Flyinghead e3a1440e25 achievements: don't log token 2024-06-19 15:04:49 +02:00
Flyinghead 0a9eaa6cb8 android: storage fixes
storage: add file update date to FileInfo.
Savestates and custom textures can be loaded from content path / ASS.
Cache last savestate update date to improve perf on android.
android: Don't use scoped storage for android < 5. Optimize listContent.
Fix getSubPath
android: instrumented storage test
2024-06-17 09:53:32 +02:00
Flyinghead e4ca99afba android ci: bump versionCode on each run 2024-06-14 15:36:12 +02:00
Flyinghead e5ccf98693 android ci: set track to internal 2024-06-14 14:31:28 +02:00
Flyinghead e832509175 android ci: missing keystore password 2024-06-14 13:16:15 +02:00
Flyinghead 977d6c6f95 android: upload to google play 2024-06-14 12:59:19 +02:00
Flyinghead 2103dd5a7a storage: add exists() method. load bios from content path. android fix
Add Storage::exists() method
Allow dc and arcade bios to be loaded from content path.
Fix android getSubPath when called on a root uri.
2024-06-14 12:39:32 +02:00
Flyinghead 9df12f950b android: target android 13
disable non-android CI jobs
2024-06-13 20:25:12 +02:00
Flyinghead 272f25ceb3 discord-rpc: disable clang-format 2024-06-13 16:49:34 +02:00
Flyinghead 46340e7e77 ui: add title to select file/folder popups. fix frame padding
android: always do write test in new home folder
2024-06-13 16:05:36 +02:00
Flyinghead aed4d21a4f android: prepare transition to sdk 30+. cache last savestate path
Migrate home folder to externalFilesDir
(/sdcard/Android/data/com.flycast.emulator/files) if running on android
10+.
Use externalFilesDir for home by default. No more onboarding on first
install.
Use content uri instead of hacking out real path since the latter won't
work on higher target sdk.
Cache last readable savestate path in hostfs::getSavestatePath(). All
content folders are scanned when not found, which is very slow with ASS
2024-06-13 15:36:29 +02:00
Flyinghead 9b4667cb38 windows: less log when Storage::getFileInfo fails 2024-06-12 11:08:24 +02:00
Flyinghead ec3ad9b328 sh4: use double for fipr and ftrv. divide before sqrt for fsrra. ssa fix
dynarec: use double to implement fipr and ftrv except on arm32
interpreter: always use double for fipr and ftrv
fsrra: perform division before square root
fmac: use std::fma or native fma op
get rid of unused dynarec op shop_swap
ssa: dead register pass must assume interpreter fallback modifies all
registers
ssa: replace reg+0 address by reg in constant propagation pass
decoder: replace address offset 0 by null param for indexed mem access
2024-06-12 10:54:15 +02:00
Flyinghead ca613db70d ui: better pause menu dpad nav. minor ui fixes
Tweak imgui nav algorithm to improve pause menu nav with dpad.
Imgui widgets name conflicts on network settings tab
2024-06-11 17:31:36 +02:00
Flyinghead 9fd48e7de3 wrong id for capcom vs snk millenium fight 2000 PRO (cvsgd) 2024-06-11 16:49:21 +02:00
Flyinghead 1277a8ff13 fix auto savestate
Automatic save state when unloading the game stopped working
Regression introduced by 6f0581032b
2024-06-11 16:44:42 +02:00
Flyinghead 8adec3f20b achievements: crash when unloading a game with active async task
Async tasks may reference the active game and will crash if it's been
unloaded/freed.
Fixes MINIDUMP-38H
2024-06-11 16:38:30 +02:00
scribam 9aa7371d82 deps: update imgui to version 1.90.8 2024-06-09 15:39:10 +02:00
scribam 0bf1877d96 cmake: use fallback git values 2024-06-09 15:38:39 +02:00
Flyinghead 4cd6278104 rend: force palette update when setting dx order. extra depth for cvs
Force palette update when changing directx color order.
Add 10k extra depth scale to Capcom vs SNK 2000 Pro and cvs.zip to fix
winner character portraits not appearing during ending.
Issue #1546
2024-06-08 16:43:52 +02:00
github-actions[bot] 14b8d4e915 Fetch translations & Recreate libretro_core_options_intl.h 2024-06-07 22:20:06 +00:00
sandboxgamedev123 ddb012bbd2 Add a 32-bit AppImage Script for Linux (#1539) 2024-06-05 15:54:41 +02:00
Flyinghead bfe09667f4 disable native depth interp for mortal kombat. force JP for vonot
Revert (again) forcing native depth interp for AMD gpus
Disable native depth interpolation for Mortal Kombat
Issue #1145
Force Japanese bios for vonot
Issue #1542
2024-06-05 15:53:08 +02:00
Flyinghead 4e3d1caf3f input: temporary logging for failed haptic effects 2024-06-04 13:27:26 +02:00
Flyinghead 6777aa39cb ui: disable dx9 selection if a naomi 2 game is running
Issue #1448
2024-06-03 19:25:22 +02:00
Flyinghead 9bdaa6c40b naomi: drop support for gdi. default to first bios region found
Use the first BIOS region found if the requested one can't be located.
2024-06-03 19:08:19 +02:00
Flyinghead 021249c321 update screenshots (flatpak, AltStore) 2024-06-02 17:33:47 +02:00
Flyinghead e7a4e64a6b android: fix imgui crash when editing virtual gamepad layout
Happens with openGL
Fixes MINIDUMP-374
2024-06-02 17:28:55 +02:00
scribam b840a4f477 windows: fix unit tests 2024-06-01 19:05:23 +02:00
Flyinghead bad55204f2 android: rename packages and activities 2024-06-01 19:03:58 +02:00
Edward Li 70fe47dacf Pretty print for Xcode 15 console 2024-06-01 11:13:24 +02:00
Edward Li 24e579ed99 Fix macOS debug build crash by providing a non empty ID (for the root of a window) 2024-06-01 11:13:24 +02:00
Flyinghead 8ddbe9212a Merge remote-tracking branch 'origin/master' into dev 2024-06-01 11:06:45 +02:00
Flyinghead adeba60ba9 input: ffb support for arcade games. rumble support (f355, 18wheeler)
SDL force feedback for racing wheels.
Support for jvs ffb (f355, 18wheeler), atomiswave (maxspeed, ftspeed)
and midi ffb (initd, clubk, kingrt66, sgdrvsim).
Simple haptic rumble for f355 and 18wheeler.
2024-06-01 11:03:14 +02:00
scribam 95de83431b uwp: fix http ContentLength assignment 2024-05-31 17:34:31 +02:00
scribam 112e05ed5d libzip: enable zstd 2024-05-31 17:34:01 +02:00
Blackbird88 90896368b8 Cheats: Sega GT (USA) - Widescreen cheat 2024-05-27 10:03:55 +02:00
Relwi ce46d1a383 Update README.md
Remove an unnecessary backtick
2024-05-27 10:03:24 +02:00
Flyinghead c1abadb6cd achievements: race condition. pause management. imgui fixes
Race condition when promise is deleted before the future is created
(login)
Require username and password before login.
Disallow pause in hardcore mode when needed.
imgui: fix some failing assertions

Issue #761
Fixes MINIDUMP-35Y, MINIDUMP-34A, MINIDUMP-35K, MINIDUMP-34Y
2024-05-27 10:02:43 +02:00
github-actions[bot] e85fa82101 Fetch translations & Recreate libretro_core_options_intl.h 2024-05-24 22:19:56 +00:00
Flyinghead 0a0d30309b achievements: run all http requests on a background thread
Fixes freeze when unlocking cheevos and other events.
Issue #761
2024-05-24 18:00:28 +02:00
Eric Warmenhoven 30e5466d90 libretro build fix on apple 2024-05-24 08:28:44 +02:00
Blackbird88 48dfab7397 Cheats: Faster Than Speed (Atomiswave) - Widescreen cheat 2024-05-24 08:28:11 +02:00
Flyinghead 4747252187 Merge remote-tracking branch 'origin/dev' 2024-05-23 10:40:57 +02:00
scribam a5608f4f22 android: update project
- Upgrade AGP dependency from 8.3.0 to 8.4.1
- Upgrade Gradle version to 8.6
- Use version catalogs
2024-05-22 16:16:07 +02:00
scribam 20652516e7 deps: update sdl to version 2.30.3 2024-05-22 16:15:40 +02:00
scribam f05e5f3582 deps: update libchdr 2024-05-22 16:15:40 +02:00
scribam 72e892a77e deps: update imgui to version 1.90.6 2024-05-22 16:15:40 +02:00
scribam 0fa3e9a37b cmake: better version conversion for uwp 2024-05-21 10:59:10 +02:00
Flyinghead 1256680a99 lr: Delay Frame Swapping should be enabled by default 2024-05-21 10:45:50 +02:00
Flyinghead 81bebdb900 cheats: fix floigan bros (pal) cheat
this cheat shouldn't be used for the ntsc version.
2024-05-21 10:41:21 +02:00
Flyinghead 6cc64c18dd network: add ports for dee dee planet, floigan bros, IGP and tetris 2024-05-21 10:40:01 +02:00
scribam 6b18ad7e3e cmake: better version conversion for uwp 2024-05-18 13:15:12 +02:00
Edward Li 2797cca5ff Always use BSD sed 2024-05-18 12:37:10 +02:00
Flyinghead b7a2e605f9 dx11: use ALLOW_TEARING flag to disable vsync if available 2024-05-18 12:36:29 +02:00
Flyinghead ec82c7b9ed gl: only display crosshairs when needed
regression due to 4f834610b3
2024-05-18 12:11:08 +02:00
github-actions[bot] 88f23958ac Fetch translations & Recreate libretro_core_options_intl.h 2024-05-17 22:19:56 +00:00
Flyinghead 4f834610b3 gl: refactor vmu and xhair drawing. Blit rendered frame only once
Refactor vmu and xhair drawing to use the same code as libretro.
Fix an issue were each rendered frame was blit twice to the backbuffer.
2024-05-17 17:37:32 +02:00
Flyinghead e2e9a54e0e std::swap is undefined for vector<bool> 2024-05-15 14:20:13 +02:00
Flyinghead cc56b0fbae vk: multi render support
Fixes Quake III split screen vs. and MSR rear view mirror.
Issue #1511
2024-05-15 14:01:58 +02:00
Flyinghead 5755c5b3c6 fix compile warning 2024-05-15 12:33:06 +02:00
Flyinghead 34216f77af naomi: fix marstv freeze
Force JP BIOS version D for this game.
Issue #1508
2024-05-15 11:55:06 +02:00
Flyinghead 21c77adc4d os_notify 2024-05-14 22:43:55 +02:00
Flyinghead 35acb7e62c ui: load savestate thumbnails asynchronously. limit thumbnail size
GetLastFrame can take max width or height.
Limit width of savestate screenshot to 640.
Load savestate thumbnail in async task.
2024-05-14 14:23:40 +02:00
Flyinghead b5f49d6c3a ios build fix 2024-05-13 16:27:31 +02:00
Flyinghead de403a6203 switch, uwp, libretro build fixes 2024-05-13 16:12:32 +02:00
Flyinghead 6f0581032b save screenshot. add screenshot to savestates
Retrieve last frame rgb data (gl, vk, dx9, dx11).
Specific save screenshot code for android, iOS and UWP.
Add Save Screenshot emu key (F12 by default)
vk: defer deletion of in-flight textures when texture cache is cleared.
vk: fix issue when updating imgui textures after a render pass has begun
(achievements)
vk: palette texture not updated after a state has been loaded.
gl: Move opengl-specific stuff into opengl imgui driver.
savestate: Add non compressed header, following by screenshot png data,
before actual savestate.

Issue #842
2024-05-13 15:47:34 +02:00
Flyinghead 83493cc14b achievements: fix size of multiple challenge indicators popup
Issue #761
2024-05-09 18:26:28 +02:00
Flyinghead 9bf60dde3c ui: bug fixes. cheats window changes
Fix boxart list navigation with DPad (regression).
Get rid of several bogus PopStyleVar/PopID.
Better navigation of pause menu buttons.
imgui: tweak NavScoreItem to help pause menu nav.
Allow achievement list navigation with DPad.
Open cheats window fullscreen. Open Add Cheat window as a modal popup.
Add game_scanner.cpp
2024-05-09 10:21:56 +02:00
Flyinghead c53a1c42c6 work around mingw-w64 init crash
commit https://sourceforge.net/p/mingw-w64/mingw-w64/ci/7b33798917a50cf023f1622eee8eba6d7874b796/
introduces a static initialization order fiasco if a static object is
calling clock_gettime() in its constructor.
2024-05-07 22:33:46 +02:00
Flyinghead 13302b87c8 move ui to its own folder 2024-05-07 22:23:51 +02:00
Flyinghead f76d05a3d5 achievements: leaderboard notifications. detailed toast message
Draw achievement notifications using imgui drawlist api
Fixes for insets
Issue #761
2024-05-07 17:50:36 +02:00
Flyinghead 763d9ce06a ui: split display_settings 2024-05-06 22:26:09 +02:00
Flyinghead 6ab43096a2 ui: use uiScaled() 2024-05-06 21:54:55 +02:00
Flyinghead ceec01ac2e ui: use imgui for vmu on pause menu. toast notifications
Allow nearest sampling with imgui textures (vmu, crosshair)
Use raii for styles and colors
2024-05-06 21:31:04 +02:00
Flyinghead 7327e52e71 ui: crash when loading asian fonts on windows
FontNo must be reset to 0 for Font Awesome.
Issue #1503
Fixes MINIDUMP-314
2024-05-06 14:45:28 +02:00
Flyinghead f04e9d4a65 achievements: better game load message when no achievements
Issue #761
2024-05-06 14:35:00 +02:00
Flyinghead ff33ff2b88 ui: change pause menu layout. add icons here and there
Always display savestate absolute date.
2024-05-05 16:02:37 +02:00
Flyinghead 43ba8953a2 vk: don't delete the ImGui driver when recreating the swap chain
It might be drawing at this point so just reset it.
2024-05-04 19:24:02 +02:00
Flyinghead 6de2f160a1 achievements: hardcore mode 2024-05-04 17:38:42 +02:00
flyinghead ccc9931de8 achievements: fix crash when loading image cache
Fixes MINIDUMP-312, MINIDUMP-313
Issue #761
2024-05-04 13:51:59 +02:00
Flyinghead fe17d459a5 ui: achievements list, new pause menu
Fix threading issue when hashing disk for RA. Protect cacheMap with
mutex.
Achievement current challenges displayed as small icons.
Embed FontAwesome symbols.
New pause menu.
Issue #761
2024-05-03 20:09:31 +02:00
Edward Li 2d4684a462 Use Xcode 15.3 2024-05-01 18:33:17 +02:00
Flyinghead 300cf0d437 better RetroAchievements UI and threading
Pop ups for authentication, game load, game completed, achievements
unlock and progress.
Handle disk changes.
Issue #761
2024-05-01 18:32:39 +02:00
Flyinghead c96e828c63 move http_client to oslib 2024-04-29 16:17:50 +02:00
Flyinghead 4666ea2fdb macos: bump minimum macOS version to 10.11 to avoid build error 2024-04-29 15:31:21 +02:00
Flyinghead 8f5f2caae6 Merge remote-tracking branch 'origin/master' into dev 2024-04-29 15:27:23 +02:00
Flyinghead 8fdd1dde3d RetroAchievements support
MVP
Issue #761
2024-04-29 14:59:47 +02:00
scribam e46815d070 ci: update netbsd and openbsd versions 2024-04-20 09:16:36 +02:00
Flyinghead de6a43bd21 savestate: drop support for legacy libretro and <v16 savestates 2024-04-16 09:40:55 +02:00
Flyinghead 336706e728 move most os_* funcs to oslib
add os_DestroyWindow and os_UpdateInputState
2024-04-12 17:37:45 +02:00
Flyinghead b378161837 lr: switch build fix 2024-04-11 18:50:49 +02:00
Flyinghead a136583189 drop dispmanx support. move switch main() to its own file
Dispmanx support is provided by SDL
Enable omx audio and set TARGET_VIDEOCORE when building for RPi3
2024-04-11 16:27:28 +02:00
Flyinghead 06a6e26588 get rid of os_GetSeconds()
replace it with std::chrono-based getTimeMs()
2024-04-11 15:25:25 +02:00
Flyinghead 5541d34a9e lr win32 build fix 2024-04-10 18:10:21 +02:00
Flyinghead 108c8a4b5d vk: move macOS video routing code from context to renderer 2024-04-10 17:31:23 +02:00
Flyinghead 9e916ca1c9 minor input and lua fixes
Make macOS keyboard class with haptic code
Call SDL_JoystickSetPlayerIndex using maple port
Add Network event for LUA
Set proper controller unique id on iOS
rumblePower wasn't copied over new mappings.
2024-04-10 17:24:47 +02:00
Flyinghead 42e98e86d0 set thread names
Name all threads to help debugging and improve crash reports (windows
only)
Add ^C handler for clean exit on linux
2024-04-10 17:08:24 +02:00
Flyinghead 010fba15a8 macOS build fix 2024-04-08 21:26:18 +02:00
Flyinghead bf249061cf thegamedb: ignore common disk ids T0000 and T0000M
These are default disk ids and shouldn't be used to identify media
2024-04-08 19:09:14 +02:00
Flyinghead 24db1422b8 ui: rearrange Settings > Video screen
Issue #665
2024-04-08 19:07:44 +02:00
Flyinghead da6c34b2fd android workflow: fetch submodules recursively (for libadrenotools) 2024-04-07 12:34:34 +02:00
Flyinghead a6c4530e22 vulkan: allow custom GPU driver loading with libadrenotools
Issue #1471
2024-04-07 12:27:54 +02:00
Flyinghead e8340bfa5e maple: implement AllStatusReq for controller and VMU 2024-04-07 11:47:42 +02:00
Flyinghead eaa22a49d1 msvc build fix 2024-04-06 19:07:27 +02:00
Flyinghead 4f87a3556e Fix vmu beep frequency 2024-04-06 17:43:19 +02:00
Flyinghead 41d418ed25 bump libchdr to match master 2024-04-06 17:21:27 +02:00
Bobby Smith 8252a28e48 [Libretro] Check for per-pixel compatibility and hide the option if not supported 2024-03-17 17:55:23 +01:00
Flyinghead e27b5dc1aa Merge remote-tracking branch 'origin/master' into dev 2024-03-16 19:40:48 +01:00
Flyinghead b0a268b89e richer discord presence using boxart from thegamesdb 2024-03-03 16:03:22 +01:00
Flyinghead 62d00578af fix compile warnings 2024-03-01 12:58:53 +01:00
Flyinghead dac5c008ab Discord Presence support
Issue #1289
2024-03-01 12:34:49 +01:00
Flyinghead 588035d9eb set currently played game name in the window title
Issue #28
2024-03-01 12:00:24 +01:00
Flyinghead b5eecb79b8 android: hid barcode scanner support 2024-02-26 16:27:18 +01:00
Flyinghead f629c352e1 fix FreeBSD x64 segfault context
Issue #1401
2024-02-26 11:27:03 +01:00
Flyinghead ff91d1101a isofs: fix long directory listing
Directory entries can't cross a sector boundary, so reading must
continue on the next one.
Add list() method
2024-02-25 15:59:22 +01:00
Flyinghead 4f1512d369 bump depth scale for NHL 2K2
Fixes helmet rendering in team selection menu
Issue #1416
2024-02-25 14:40:37 +01:00
Flyinghead 2dde1d5e7b sh4: fix P4 region mapping and on chip ram addressing
P4 region is normally mapped outside of the sq and system registers
areas (E4-EF, F8-FE).
Fixes NHL 2K2 missing helmet and jersey textures. Issue #1416
Fixes invalid geometry in worldkicks series (using interpreter or 4 GB
vmem space)
Fix On Chip RAM addressing: bit 13 or 25 is used to select the bank.
2024-02-25 14:37:27 +01:00
scribam 3c8769cb5c deps: sync imgui_impl_vulkan.cpp with upstream 2024-02-24 22:08:40 +01:00
scribam ba12c01ab8 deps: update imgui to version 1.90.4 2024-02-24 22:08:40 +01:00
Flyinghead 713739bbc7 sdl: support multiple mice when allowed by the platform 2024-02-24 21:33:40 +01:00
Flyinghead 4667d17d78 naomi: fix shaktam inputs
Issue #1420
2024-02-24 19:42:41 +01:00
scribam b71541f8dd cmake: improved parallelism in msbuild 2024-02-22 09:21:34 +01:00
scribam 56cad843c9 ci: use cross-platform-actions/action to build on bsd systems 2024-02-21 08:46:27 +01:00
scribam 1b0781c680 bsd: update segfault context for arm64 2024-02-21 08:46:27 +01:00
scribam 0c5e79d618 deps: update imgui to version 1.90.3 2024-02-17 17:40:22 +01:00
scribam 5c8d7021f6 linux: use egl with x11 instead of glx 2024-02-17 17:38:39 +01:00
scribam 8d2bcdf35e deps: update libchdr 2024-02-17 17:37:32 +01:00
scribam eb2826f6d3 deps: update libzip to version 1.10.1 2024-02-15 10:00:56 +01:00
scribam 6cb929953c ci: use latest devkitpro docker image 2024-02-10 12:41:51 +01:00
Flyinghead 232924d88a init drive when running .elf. Skip special settings for BIOS and .elf. 2024-02-10 12:41:17 +01:00
Flyinghead 90b13a40ab gladLoader: check return code and log. cheats: light refactoring 2024-02-10 12:06:48 +01:00
Flyinghead a50f5765da Merge remote-tracking branch 'origin/master' into dev 2024-02-10 11:58:39 +01:00
Flyinghead 434083c716 samsptk: use cheat instead of extra depth scale
Use a cheat to fix the game bug instead of dealing with ginormous depth
values.
2024-02-07 19:41:03 +01:00
Flyinghead d9d91381b5 gdrom: delay "no disk" reporting to let the BIOS play the boot animation
Thanks to kihato for the prototype code.
Issue #587
2024-02-07 16:11:25 +01:00
Flyinghead 531c6f94d5 pvr: apply a negative bias to background plane depth
Fixes skybox in Xtreme Sports. Issue #1381
Fixes background clipping in Blue Stinger (JP) intro. Issue #721
Fixes Windows CE yuv FMV black screen (4x4 EVO, Armada, Carsear's
Palace, Giant Killers, PBA bowling, Starlancer, Tomr Raider, Wild Metal,
Who wants to beat up...)

Get rid of ForceWindowsCE option
Force PAL for Super Runabout (EU)
2024-02-07 16:02:55 +01:00
Flyinghead 9aa9b5bebc ui: replace Exit by Close Game. Better format for some UI values.
Issue #1383
2024-02-07 11:05:09 +01:00
Flyinghead e592650afc gdrom: set correct lead-out FAD of single-density area
Use end FAD +1 of track 2 as start of lead-out for single density area.
gdi: set track end FAD based on track size, not start of next track
chd: ignore pad frames when calculating end FAD
cdi: end FAD was one off
Issue #1386
2024-02-06 11:07:20 +01:00
955 changed files with 198440 additions and 90864 deletions

No files matched your search

+1 -1
View File
@@ -12,7 +12,7 @@ assignees: ''
Platform / OS / Hardware:
Github hash:
Flycast version:
Hardware:
+34 -20
View File
@@ -1,41 +1,57 @@
name: Android CI
name: Android
on: [push, pull_request]
on:
push:
branches-ignore:
- 'l10n_**'
pull_request:
jobs:
build:
name: Android
runs-on: ubuntu-latest
steps:
- name: Set up build environment
run: |
sudo apt-get update
sudo apt-get -y install ccache libcurl4-openssl-dev ninja-build
sudo apt-get -y install ccache cmake libcurl4-openssl-dev ninja-build
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: true
- uses: actions/setup-java@v4
submodules: recursive
- uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
cache: 'gradle'
- uses: actions/cache@v4
- uses: actions/cache@v5
with:
path: ~/.ccache
key: android-ccache-${{ github.sha }}
restore-keys: android-ccache-
- name: Disable release signing
run: sed -i 's/signingConfig signingConfigs.release/signingConfig signingConfigs.debug/g' shell/android-studio/flycast/build.gradle
if: github.repository != 'flyinghead/flycast' || github.event_name != 'push'
- name: Bump version code
uses: chkfung/[email protected]
with:
gradlePath: shell/android-studio/flycast/build.gradle
versionCode: ${{ github.run_number }}
- name: Gradle
working-directory: shell/android-studio
run: ./gradlew assembleRelease --parallel
run: ./gradlew assembleRelease bundleRelease --parallel
env:
SENTRY_UPLOAD_URL: ${{ secrets.SENTRY_UPLOAD_URL }}
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: flycast-release.apk
path: shell/android-studio/flycast/build/outputs/apk/release/flycast-release.apk
@@ -58,18 +74,16 @@ jobs:
mv libflycast.so.sym symbols/libflycast.so/$BUILD_ID
done
- name: Configure AWS Credentials
id: aws-credentials
uses: aws-actions/configure-aws-credentials@v4
- name: Setup Rclone
uses: AnimMouse/setup-rclone@v1
with:
aws-access-key-id: AKIAJOZQS4H2PHQWYFCA
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
aws-region: us-east-2
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push'
rclone_config: ${{ secrets.RCLONE_CONFIG }}
- name: Upload to S3
run: aws s3 sync shell/android-studio/flycast/build/outputs/apk/release s3://flycast-builds/android/${GITHUB_REF#refs/}-$GITHUB_SHA --acl public-read --exclude='*.json' --follow-symlinks
if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }}
run: |
cp shell/android-studio/flycast/build/outputs/bundle/release/*.aab shell/android-studio/flycast/build/outputs/apk/release/
rclone copy shell/android-studio/flycast/build/outputs/apk/release scaleway:flycast-builds/android/${GITHUB_REF#refs/}-$GITHUB_SHA --exclude '*.json'
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push'
- name: Setup Sentry CLI
uses: mathieu-bour/setup-sentry-cli@v2
@@ -92,4 +106,4 @@ jobs:
shell: bash
env:
SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
if: ${{ env.SENTRY_TOKEN != '' }}
if: ${{ env.SENTRY_TOKEN != '' && github.event_name == 'push' }}
+18 -13
View File
@@ -1,6 +1,10 @@
name: BSD CI
name: BSD
on: [push, pull_request]
on:
push:
branches-ignore:
- 'l10n_**'
pull_request:
jobs:
build:
@@ -11,32 +15,33 @@ jobs:
matrix:
operating_system: [ freebsd, netbsd, openbsd ]
architecture: [ arm64, x86-64 ]
libretro: [ OFF, ON ]
include:
- operating_system: freebsd
version: '14.0'
pkginstall: sudo pkg install -y alsa-lib ccache cmake evdev-proto git libao libevdev libudev-devd libzip miniupnpc ninja pkgconf pulseaudio sdl2
version: '15.0'
pkginstall: sudo pkg update && sudo pkg install -y alsa-lib ccache cmake evdev-proto git libao libevdev libudev-devd libzip lua54 miniupnpc ninja pkgconf pulseaudio sdl2 libcdio
- operating_system: netbsd
version: '9.3'
pkginstall: sudo pkgin update && sudo pkgin -y install alsa-lib ccache cmake gcc12 git libao libzip miniupnpc ninja-build pkgconf pulseaudio SDL2 && export PATH=/usr/pkg/gcc12/bin:$PATH
version: '10.1'
pkginstall: sudo pkgin update && sudo pkgin -y install alsa-lib ccache clang cmake git libao libzip lua54 miniupnpc ninja-build pkgconf pulseaudio SDL2 libcdio
- operating_system: openbsd
version: '7.4'
pkginstall: sudo pkg_add ccache cmake git libao libzip miniupnpc ninja pkgconf pulseaudio sdl2
version: '7.8'
pkginstall: sudo pkg_add -u && sudo pkg_add ccache cmake git libao libzip miniupnpc ninja pkgconf pulseaudio sdl2 libcdio
exclude:
- architecture: arm64
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: true
submodules: recursive
- uses: actions/cache@v4
- uses: actions/cache@v5
with:
path: ${{ env.CCACHE_DIR }}
key: ccache-${{ matrix.operating_system }}-${{ matrix.architecture }}-${{ github.sha }}
restore-keys: ccache-${{ matrix.operating_system }}-${{ matrix.architecture }}-
- uses: cross-platform-actions/action@v0.23.0
- uses: cross-platform-actions/[email protected]1.0
with:
operating_system: ${{ matrix.operating_system }}
architecture: ${{ matrix.architecture }}
@@ -44,5 +49,5 @@ jobs:
environment_variables: CCACHE_DIR
run: |
${{ matrix.pkginstall }}
cmake -B build -DCMAKE_BUILD_TYPE=Release -G Ninja
cmake -B build -DUSE_LIBCDIO=ON -DCMAKE_BUILD_TYPE=Release -G Ninja -DLIBRETRO=${{ matrix.libretro }}
cmake --build build --config Release
+34 -35
View File
@@ -1,6 +1,10 @@
name: C/C++ CI
name: Linux, macOS, Windows
on: [push, pull_request]
on:
push:
branches-ignore:
- 'l10n_**'
pull_request:
jobs:
build:
@@ -18,23 +22,22 @@ jobs:
matrix:
config:
- {name: i686-pc-windows-msvc, os: windows-latest, shell: cmd, arch: x86, cmakeArgs: -G Ninja, buildType: Release}
- {name: apple-darwin, os: macos-latest, shell: sh, cmakeArgs: -G Xcode -DAPPLE_BREAKPAD=ON, destDir: osx, buildType: RelWithDebInfo}
- {name: apple-ios, os: macos-latest, shell: sh, cmakeArgs: -DCMAKE_SYSTEM_NAME=iOS -G Xcode, destDir: ios, buildType: Release}
- {name: x86_64-pc-linux-gnu, os: ubuntu-20.04, shell: sh, cmakeArgs: -G Ninja, destDir: linux, buildType: RelWithDebInfo}
- {name: x86_64-pc-windows-msvc, os: windows-latest, shell: cmd, arch: x64, cmakeArgs: -G Ninja, buildType: Release}
- {name: x86_64-w64-mingw32, os: windows-latest, shell: 'msys2 {0}', cmakeArgs: -G Ninja, destDir: win, buildType: RelWithDebInfo}
- {name: libretro-x86_64-pc-linux-gnu, os: ubuntu-latest, shell: sh, cmakeArgs: -DLIBRETRO=ON -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -G Ninja, buildType: Release}
- {name: libretro-x86_64-w64-mingw32, os: windows-latest, shell: 'msys2 {0}', cmakeArgs: -DLIBRETRO=ON -G Ninja, buildType: Release}
- {name: apple-darwin, os: macos-latest, shell: sh, cmakeArgs: -G Xcode -DUSE_DISCORD=ON, destDir: osx, buildType: RelWithDebInfo}
- {name: x86_64-pc-linux-gnu, os: ubuntu-22.04, shell: sh, cmakeArgs: -G Ninja -DUSE_DISCORD=ON -DUSE_LIBCDIO=ON, destDir: linux, buildType: RelWithDebInfo}
- {name: x86_64-pc-windows-msvc, os: windows-latest, shell: cmd, arch: x64, cmakeArgs: -G Ninja -DUSE_DISCORD=ON, buildType: Release}
- {name: x86_64-w64-mingw32, os: windows-latest, shell: 'msys2 {0}', cmakeArgs: -G Ninja -DUSE_DISCORD=ON -DUSE_LIBCDIO=ON, destDir: win, buildType: RelWithDebInfo}
- {name: libretro-x86_64-pc-linux-gnu, os: ubuntu-22.04, shell: sh, cmakeArgs: -DLIBRETRO=ON -DUSE_LIBCDIO=ON -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -G Ninja, buildType: Release}
- {name: libretro-x86_64-w64-mingw32, os: windows-latest, shell: 'msys2 {0}', cmakeArgs: -DLIBRETRO=ON -DUSE_LIBCDIO=ON -G Ninja, buildType: Release}
steps:
- name: Set up build environment (macOS)
run: |
sudo xcode-select -switch /Applications/Xcode_15.3.app
# Unlink and re-link to prevent errors when github mac runner images install python outside of brew. See https://github.com/actions/setup-python/issues/577
brew list -1 | grep python | while read formula; do brew unlink $formula; brew link --overwrite $formula; done
brew update || :
brew install libao ldid ninja pulseaudio
VULKAN_VER=1.3.261.1 && aria2c https://sdk.lunarg.com/sdk/download/$VULKAN_VER/mac/vulkansdk-macos-$VULKAN_VER.dmg
brew install libao ldid pulseaudio
brew uninstall --ignore-dependencies zstd
VULKAN_VER=1.3.290.0 && aria2c https://sdk.lunarg.com/sdk/download/$VULKAN_VER/mac/vulkansdk-macos-$VULKAN_VER.dmg
hdiutil attach ./vulkansdk-macos-*.dmg -mountpoint /Volumes/VulkanSDK
sudo /Volumes/VulkanSDK/InstallVulkan.app/Contents/MacOS/InstallVulkan --root $HOME/VulkanSDK --accept-licenses --default-answer --confirm-command install
hdiutil detach /Volumes/VulkanSDK
@@ -45,15 +48,17 @@ jobs:
run: |
sudo add-apt-repository ppa:christianrauch/libdecoration
sudo apt-get update
sudo apt-get -y install ccache libao-dev libasound2-dev libevdev-dev libgl1-mesa-dev liblua5.3-dev libminiupnpc-dev libpulse-dev libsdl2-dev libudev-dev libzip-dev ninja-build libcurl4-openssl-dev
sudo apt-get -y install ccache libao-dev libasound2-dev libevdev-dev libgl1-mesa-dev liblua5.3-dev libminiupnpc-dev libpulse-dev libsdl2-dev libudev-dev libzip-dev ninja-build libcurl4-openssl-dev libcdio-dev libfuse2 locales
sudo apt-get -y install libwayland-dev libdecor-0-dev libaudio-dev libjack-dev libsndio-dev libsamplerate0-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxkbcommon-dev libdrm-dev libgbm-dev libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev
sudo sed -i 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/g' /etc/locale.gen
sudo locale-gen
if: runner.os == 'Linux'
- name: Set up build environment (Windows, MinGW)
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
install: git make mingw-w64-x86_64-ccache mingw-w64-x86_64-cmake mingw-w64-x86_64-lua mingw-w64-x86_64-ninja mingw-w64-x86_64-SDL2 mingw-w64-x86_64-toolchain
install: git make mingw-w64-x86_64-ccache mingw-w64-x86_64-cmake mingw-w64-x86_64-lua mingw-w64-x86_64-ninja mingw-w64-x86_64-SDL2 mingw-w64-x86_64-toolchain mingw-w64-x86_64-libcdio
if: matrix.config.shell == 'msys2 {0}'
- name: Set up build environment (Windows, Visual Studio)
@@ -67,20 +72,16 @@ jobs:
arch: ${{ matrix.config.arch }}
if: matrix.config.shell == 'cmd'
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: true
submodules: recursive
- name: Compile a universal OpenMP (macOS)
run: HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew reinstall --build-from-source --formula ./shell/apple/libomp.rb
run: HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 HOMEBREW_DEVELOPER=1 brew reinstall --build-from-source --formula ./shell/apple/libomp.rb
if: matrix.config.name == 'apple-darwin'
- name: Compile OpenMP.xcframework (iOS)
run: ./shell/apple/emulator-ios/OpenMP/build_ios_openmp.sh --disableSimulator
if: matrix.config.name == 'apple-ios'
- uses: actions/cache@v4
- uses: actions/cache@v5
with:
path: ${{ env.CCACHE_DIR }}
key: ccache-${{ matrix.config.name }}-${{ github.sha }}
@@ -126,10 +127,12 @@ jobs:
rm artifact/bin/flycast
if: matrix.config.name == 'x86_64-pc-linux-gnu'
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: flycast-${{ matrix.config.name }}
path: artifact/bin
path: |
artifact/bin
artifact/lib/libretro
- name: Package app (macos)
run: |
@@ -143,19 +146,15 @@ jobs:
rm artifact/bin/flycast.exe
if: matrix.config.name == 'x86_64-w64-mingw32'
- name: Configure AWS Credentials
id: aws-credentials
uses: aws-actions/configure-aws-credentials@v4
- name: Setup Rclone
uses: AnimMouse/setup-rclone@v1
with:
aws-access-key-id: AKIAJOZQS4H2PHQWYFCA
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
aws-region: us-east-2
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push' && matrix.config.destDir != ''
rclone_config: ${{ secrets.RCLONE_CONFIG }}
- name: Upload to S3
run: aws s3 sync artifact/bin s3://flycast-builds/${{ matrix.config.destDir }}/${GITHUB_REF#refs/}-$GITHUB_SHA --acl public-read --follow-symlinks
run: rclone copy artifact/bin scaleway:flycast-builds/${{ matrix.config.destDir }}/${GITHUB_REF#refs/}-$GITHUB_SHA
shell: bash
if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }}
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push' && matrix.config.destDir != ''
- name: Setup Sentry CLI
uses: mathieu-bour/setup-sentry-cli@v2
@@ -178,5 +177,5 @@ jobs:
shell: bash
env:
SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
if: ${{ env.SENTRY_TOKEN != '' && (matrix.config.name == 'x86_64-w64-mingw32' || matrix.config.name == 'apple-darwin' || matrix.config.name == 'x86_64-pc-linux-gnu') }}
if: ${{ env.SENTRY_TOKEN != '' && (matrix.config.name == 'x86_64-w64-mingw32' || matrix.config.name == 'apple-darwin' || matrix.config.name == 'x86_64-pc-linux-gnu') && github.event_name == 'push' }}
+3 -3
View File
@@ -15,18 +15,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Setup Java JDK
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
java-version: 18
distribution: zulu
- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v6
with:
python-version: '3.10'
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Upload Source
shell: bash
+4 -4
View File
@@ -12,18 +12,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Setup Java JDK
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
java-version: 18
distribution: zulu
- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v6
with:
python-version: '3.10'
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
@@ -43,7 +43,7 @@ jobs:
git commit -m "Fetch translations & Recreate libretro_core_options_intl.h"
- name: GitHub Push
uses: ad-m/github-push-action@v0.8.0
uses: ad-m/github-push-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
+21 -18
View File
@@ -1,10 +1,14 @@
name: Nintendo Switch CI
name: Nintendo Switch
on: [push, pull_request]
on:
push:
branches-ignore:
- 'l10n_**'
pull_request:
jobs:
build:
name: ${{ matrix.config.name }}
name: Switch ${{ matrix.config.name }}
runs-on: ubuntu-latest
container: devkitpro/devkita64:latest
@@ -18,17 +22,17 @@ jobs:
- name: Set up build environment
run: |
sudo apt-get update
sudo apt-get -y install awscli ccache
sudo apt-get -y install ccache cmake
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: true
submodules: recursive
- name: Mark git repository as safe
run: git config --global --add safe.directory $PWD
- uses: actions/cache@v4
- uses: actions/cache@v5
with:
path: ~/.ccache
key: ccache-switch-${{ matrix.config.name }}-${{ github.sha }}
@@ -39,24 +43,23 @@ jobs:
$DEVKITPRO/portlibs/switch/bin/aarch64-none-elf-cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=artifact -G Ninja ${{ matrix.config.cmakeArgs }}
cmake --build build --config Release --target install
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: flycast-switch-${{ matrix.config.name }}
path: artifact/bin
path: |
artifact/bin
artifact/lib/libretro
- name: Package app
run: zip -m artifact/bin/flycast.nro.zip artifact/bin/flycast.nro
if: hashFiles('artifact/bin/flycast.nro') != ''
- name: Configure AWS Credentials
id: aws-credentials
uses: aws-actions/configure-aws-credentials@v4
- name: Setup Rclone
uses: AnimMouse/setup-rclone@v1
with:
aws-access-key-id: AKIAJOZQS4H2PHQWYFCA
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
aws-region: us-east-2
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push' && matrix.config.destDir != ''
rclone_config: ${{ secrets.RCLONE_CONFIG }}
version: v1.69.1
- name: Upload to S3
run: aws s3 sync artifact/bin s3://flycast-builds/${{ matrix.config.destDir }}/${GITHUB_REF#refs/}-$GITHUB_SHA --acl public-read --follow-symlinks
if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }}
run: rclone copy artifact/bin scaleway:flycast-builds/${{ matrix.config.destDir }}/${GITHUB_REF#refs/}-$GITHUB_SHA
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push' && matrix.config.destDir != ''
+22 -17
View File
@@ -1,20 +1,29 @@
name: Windows UWP CI
name: Xbox, UWP
on: [push, pull_request]
on:
push:
branches-ignore:
- 'l10n_**'
pull_request:
jobs:
build:
name: UWP
runs-on: windows-latest
strategy:
matrix:
arch: [ Win32, x64, ARM64 ]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: true
submodules: recursive
- name: CMake
run: |
cmake -B build -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 17 2022" -A x64 -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.22000.0
cmake -B build -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 17 2022" -A ${{ matrix.arch }} -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.22000.0
cmake --build build --config Release -- /m
shell: cmd
@@ -23,7 +32,7 @@ jobs:
- name: Package app
run: |
mkdir build\artifact
cd build\AppPackages\flycast\flycast_*_x64_Test
cd build\AppPackages\flycast\flycast_*_Test
mkdir tmp
ren *.msix flycast.msix
makeappx.exe unpack /p .\flycast.msix /d tmp
@@ -34,21 +43,17 @@ jobs:
run: signtool sign /f shell\uwp\sign_cert.pfx /p '${{ secrets.SIGN_CERT_PWD }}' /v /fd SHA256 build\artifact\flycast.appx
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push'
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
with:
name: flycast-uwp
name: flycast-uwp-${{ matrix.arch }}
path: build/artifact
- name: Configure AWS Credentials
id: aws-credentials
uses: aws-actions/configure-aws-credentials@v4
- name: Setup Rclone
uses: AnimMouse/setup-rclone@v1
with:
aws-access-key-id: AKIAJOZQS4H2PHQWYFCA
aws-secret-access-key: ${{ secrets.S3_SECRET_KEY }}
aws-region: us-east-2
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push'
rclone_config: ${{ secrets.RCLONE_CONFIG }}
- name: Upload to S3
run: aws s3 sync build/artifact s3://flycast-builds/xbox/${GITHUB_REF#refs/}-$GITHUB_SHA --acl public-read --follow-symlinks
run: rclone copy build/artifact scaleway:flycast-builds/xbox/${GITHUB_REF#refs/}-$GITHUB_SHA
shell: bash
if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }}
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push' && matrix.arch == 'x64'
+3
View File
@@ -17,3 +17,6 @@ cmake-build-*/
# Dependencies from .gitmodules
core/deps/breakpad/
core/deps/glslang/
.cache/
compile_commands.json
CMakeUserPresets.json
+19 -7
View File
@@ -9,39 +9,46 @@
variables:
GIT_SUBMODULE_STRATEGY: recursive
CORENAME: flycast
CORE_ARGS: -DLIBRETRO=ON -DCMAKE_BUILD_TYPE=Release
CORE_ARGS: -DLIBRETRO=ON -DUSE_LIBCDIO=ON
.core-defs-linux:
extends: .core-defs
variables:
CORE_ARGS: -DLIBRETRO=ON -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE -DCMAKE_BUILD_TYPE=Release
CORE_ARGS: -DLIBRETRO=ON -DUSE_LIBCDIO=ON -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE
CC: /usr/bin/gcc-12
CXX: /usr/bin/g++-12
.core-defs-osx-x64:
extends: .core-defs
variables:
CORE_ARGS: -DLIBRETRO=ON -G Xcode -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64
CORE_ARGS: -DLIBRETRO=ON -G Xcode -DCMAKE_OSX_ARCHITECTURES=x86_64
EXTRA_PATH: Release
.core-defs-osx-arm64:
extends: .core-defs
variables:
CORE_ARGS: -DLIBRETRO=ON -G Xcode -DCMAKE_BUILD_TYPE=Release
CORE_ARGS: -DLIBRETRO=ON -G Xcode
EXTRA_PATH: Release
.core-defs-ios-arm64:
extends: .core-defs
variables:
CORE_ARGS: -DLIBRETRO=ON -DCMAKE_BUILD_TYPE=Release
CORE_ARGS: -DLIBRETRO=ON -DUSE_OPENMP=OFF -DCMAKE_OSX_DEPLOYMENT_TARGET=13.0
IOS_MINVER: 13.0
MINVER: 13.0
.core-defs-android:
extends: .core-defs
script:
- cmake $CORE_ARGS -DANDROID_PLATFORM=android-$API_LEVEL -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake -DANDROID_STL=c++_static -DANDROID_ABI=$ANDROID_ABI -DANDROID_ARM_MODE=arm "$CMAKE_SOURCE_ROOT" -B$BUILD_DIR
- echo y | /android-sdk-linux/cmdline-tools/latest/bin/sdkmanager "ndk;${ANDROID_NDK_VERSION}"
- cmake -DLIBRETRO=ON -DUSE_OPENMP=OFF -DANDROID_PLATFORM=android-$API_LEVEL -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake -DANDROID_STL=c++_static -DANDROID_ABI=$ANDROID_ABI -DANDROID_ARM_MODE=arm -DANDROID_WEAK_API_DEFS=ON "$CMAKE_SOURCE_ROOT" -B$BUILD_DIR
- cmake --build $BUILD_DIR --target ${CORENAME}_libretro --config Release -- -j $NUMPROC
- mv $BUILD_DIR/${CORENAME}_libretro.so $LIBNAME
- if [ $STRIP_CORE_LIB -eq 1 ]; then $NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip $LIBNAME; fi
variables:
API_LEVEL: 18
ANDROID_NDK_VERSION: 29.0.14206865
API_LEVEL: 21
NDK_ROOT: /android-sdk-linux/ndk/$ANDROID_NDK_VERSION
# Inclusion templates, required for the build to work
include:
@@ -108,18 +115,22 @@ libretro-build-linux-x64:
extends:
- .libretro-linux-cmake-x86_64
- .core-defs-linux
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-amd64-ubuntu:backports
# Linux 32-bit
libretro-build-linux-i686:
extends:
- .libretro-linux-cmake-x86
- .core-defs-linux
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-i386-ubuntu:backports
# MacOS 64-bit
libretro-build-osx-x64:
extends:
- .libretro-osx-cmake-x86
- .core-defs-osx-x64
tags:
- mac-apple-silicon
# MacOS arm 64-bit
libretro-build-osx-arm64:
@@ -169,3 +180,4 @@ libretro-build-tvos-arm64:
extends:
- .libretro-tvos-cmake-arm64
- .core-defs-ios-arm64
+31 -1
View File
@@ -3,7 +3,7 @@
url = https://github.com/libsdl-org/SDL.git
[submodule "core/deps/libchdr"]
path = core/deps/libchdr
url = https://github.com/rtissera/libchdr.git
url = https://github.com/flyinghead/libchdr.git
ignore = dirty
[submodule "core/deps/luabridge"]
path = core/deps/luabridge
@@ -29,3 +29,33 @@
[submodule "core/deps/Spout"]
path = core/deps/Spout
url = https://github.com/vkedwardli/Spout2.git
[submodule "core/deps/discord-rpc"]
path = core/deps/discord-rpc
url = https://github.com/harmonytf/discord-rpc
[submodule "core/deps/libadrenotools"]
path = core/deps/libadrenotools
url = https://github.com/bylaws/libadrenotools
[submodule "core/deps/rcheevos"]
path = core/deps/rcheevos
url = https://github.com/RetroAchievements/rcheevos.git
[submodule "core/deps/googletest"]
path = core/deps/googletest
url = https://github.com/google/googletest.git
[submodule "core/deps/asio"]
path = core/deps/asio
url = https://github.com/flyinghead/asio.git
[submodule "core/deps/xbyak"]
path = core/deps/xbyak
url = https://github.com/herumi/xbyak.git
[submodule "core/deps/libjuice"]
path = core/deps/libjuice
url = https://github.com/paullouisageneau/libjuice.git
[submodule "core/deps/websocketpp"]
path = core/deps/websocketpp
url = https://github.com/zaphoyd/websocketpp.git
[submodule "core/deps/DreamPicoPort-API"]
path = core/deps/DreamPicoPort-API
url = https://github.com/OrangeFox86/DreamPicoPort-API.git
[submodule "core/deps/tinygettext"]
path = core/deps/tinygettext
url = https://github.com/flyinghead/tinygettext
+344 -535
View File
File diff suppressed because it is too large. Load diff
+23
View File
@@ -0,0 +1,23 @@
{
"version": 2,
"configurePresets": [
{
"name": "clang",
"generator": "Ninja",
"binaryDir": "build-clang",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "gcc",
"generator": "Ninja",
"binaryDir": "build-gcc",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
}
]
}
+8 -2
View File
@@ -6,7 +6,7 @@
[![Windows UWP CI](https://github.com/flyinghead/flycast/actions/workflows/uwp.yml/badge.svg)](https://github.com/flyinghead/flycast/actions/workflows/uwp.yml)
[![BSD CI](https://github.com/flyinghead/flycast/actions/workflows/bsd.yml/badge.svg)](https://github.com/flyinghead/flycast/actions/workflows/bsd.yml)
![flycast logo](https://github.com/flyinghead/flycast/raw/master/shell/linux/flycast.png)
<img src="shell/linux/flycast.png" alt="flycast logo" width="150"/>
**Flycast** is a multi-platform Sega Dreamcast, Naomi, Naomi 2, and Atomiswave emulator derived from [**reicast**](https://github.com/skmp/reicast-emulator).
@@ -16,6 +16,8 @@ Join us on our [**Discord server**](https://discord.gg/X8YWP8w) for a chat.
## Install
### Android ![android](https://flyinghead.github.io/flycast-builds/android.jpg)
Install Flycast from [**Google Play**](https://play.google.com/store/apps/details?id=com.flycast.emulator).
### Flatpak (Linux ![ubuntu logo](https://flyinghead.github.io/flycast-builds/ubuntu.png))
1. [Set up Flatpak](https://www.flatpak.org/setup/).
@@ -36,6 +38,10 @@ Join us on our [**Discord server**](https://discord.gg/X8YWP8w) for a chat.
`brew install --cask flycast`
### iOS
Due to persistent harassment from an iOS user, support for this platform has been dropped.
### Xbox One/Series ![xbox logo](https://flyinghead.github.io/flycast-builds/xbox.png)
Grab the latest build from [**the builds page**](https://flyinghead.github.io/flycast-builds/), or the [**GitHub Actions**](https://github.com/flyinghead/flycast/actions/workflows/uwp.yml). Then install it using the **Xbox Device Portal**.
@@ -48,7 +54,7 @@ Get fresh builds for your system [**on the builds page**](https://flyinghead.git
### Build instructions:
```
$ git clone --recursive https://github.com/flyinghead/flycast.git`
$ git clone --recursive https://github.com/flyinghead/flycast.git
$ cd flycast
$ mkdir build && cd build
$ cmake ..
+3
View File
@@ -0,0 +1,3 @@
target_sources(${PROJECT_NAME} PRIVATE
achievements.cpp
achievements.h)
File diff suppressed because it is too large. Load diff
+72
View File
@@ -0,0 +1,72 @@
/*
This file is part of Flycast.
Flycast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Flycast is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "types.h"
#include <future>
#include <vector>
namespace achievements
{
#ifdef USE_RACHIEVEMENTS
struct Game
{
std::string image;
std::string title;
u32 unlockedAchievements;
u32 totalAchievements;
u32 points;
u32 totalPoints;
};
struct Achievement
{
Achievement() = default;
Achievement(const std::string& image, const std::string& title, const std::string& description, const std::string& category, const std::string& status)
: image(image), title(title), description(description), category(category), status(status) {}
std::string image;
std::string title;
std::string description;
std::string category;
std::string status;
};
bool init();
void term();
std::future<void> login(const char *username, const char *password);
void logout();
bool isLoggedOn();
bool isActive();
Game getCurrentGame();
std::vector<Achievement> getAchievementList();
bool canPause();
#else
static inline bool isActive() {
return false;
}
static inline bool canPause() {
return true;
}
#endif
void serialize(Serializer& ser);
void deserialize(Deserializer& deser);
}
+3 -3
View File
@@ -19,9 +19,9 @@
along with reicast. If not, see <https://www.gnu.org/licenses/>.
*/
#include "7zArchive.h"
#include "deps/lzma/7z.h"
#include "deps/lzma/7zCrc.h"
#include "deps/lzma/Alloc.h"
#include "lzma/7z.h"
#include "lzma/7zCrc.h"
#include "lzma/Alloc.h"
#include <cstring>
+2 -2
View File
@@ -21,8 +21,8 @@
#pragma once
#include "archive.h"
#include "deps/lzma/7z.h"
#include "deps/lzma/7zFile.h"
#include "lzma/7z.h"
#include "lzma/7zFile.h"
#include <algorithm>
#include <cstring>
+9
View File
@@ -0,0 +1,9 @@
target_sources(${PROJECT_NAME} PRIVATE
7zArchive.cpp
7zArchive.h
archive.cpp
archive.h
rzip.cpp
rzip.h
ZipArchive.cpp
ZipArchive.h)
+13 -3
View File
@@ -47,7 +47,7 @@ ArchiveFile* ZipArchive::OpenFile(const char* name)
return nullptr;
zip_stat_t stat;
zip_stat(zip, name, 0, &stat);
return new ZipArchiveFile(zip_file, stat.size);
return new ZipArchiveFile(zip_file, stat.size, stat.name);
}
static zip_file *zip_fopen_by_crc(zip_t *za, u32 crc, int flags, zip_uint64_t& index)
@@ -77,7 +77,7 @@ ArchiveFile* ZipArchive::OpenFileByCrc(u32 crc)
zip_stat_t stat;
zip_stat_index(zip, index, 0, &stat);
return new ZipArchiveFile(zip_file, stat.size);
return new ZipArchiveFile(zip_file, stat.size, stat.name);
}
u32 ZipArchiveFile::Read(void* buffer, u32 length)
@@ -104,5 +104,15 @@ ArchiveFile *ZipArchive::OpenFirstFile()
return nullptr;
zip_stat_t stat;
zip_stat_index(zip, 0, 0, &stat);
return new ZipArchiveFile(zipFile, stat.size);
return new ZipArchiveFile(zipFile, stat.size, stat.name);
}
ArchiveFile *ZipArchive::OpenFileByIndex(size_t index)
{
zip_file_t *zipFile = zip_fopen_index(zip, index, 0);
if (zipFile == nullptr)
return nullptr;
zip_stat_t stat;
zip_stat_index(zip, index, 0, &stat);
return new ZipArchiveFile(zipFile, stat.size, stat.name);
}
+10 -6
View File
@@ -31,11 +31,11 @@ public:
ArchiveFile* OpenFile(const char* name) override;
ArchiveFile* OpenFileByCrc(u32 crc) override;
bool Open(const void *data, size_t size);
ArchiveFile *OpenFirstFile();
protected:
bool Open(FILE *file) override;
bool Open(const void *data, size_t size);
ArchiveFile *OpenFirstFile();
ArchiveFile *OpenFileByIndex(size_t index);
private:
zip_t *zip = nullptr;
@@ -44,8 +44,8 @@ private:
class ZipArchiveFile : public ArchiveFile
{
public:
ZipArchiveFile(zip_file_t *zip_file, size_t length)
: zip_file(zip_file), _length(length) {}
ZipArchiveFile(zip_file_t *zip_file, size_t length, const char *name)
: zip_file(zip_file), _length(length), name(name) {}
~ZipArchiveFile() override {
zip_fclose(zip_file);
}
@@ -53,8 +53,12 @@ public:
size_t length() override {
return _length;
}
const char *getName() override {
return name;
}
private:
zip_file_t *zip_file;
size_t _length;
const char *name;
};
+1
View File
@@ -28,6 +28,7 @@ public:
virtual ~ArchiveFile() = default;
virtual u32 Read(void *buffer, u32 length) = 0;
virtual size_t length() = 0;
virtual const char *getName() { return nullptr; }
};
class Archive
+20 -10
View File
@@ -23,14 +23,11 @@
const u8 RZipHeader[8] = { '#', 'R', 'Z', 'I', 'P', 'v', 1, '#' };
bool RZipFile::Open(const std::string& path, bool write)
bool RZipFile::Open(FILE *file, bool write)
{
verify(file == nullptr);
this->write = write;
file = nowide::fopen(path.c_str(), write ? "wb" : "rb");
if (file == nullptr)
return false;
verify(this->file == nullptr);
verify(file != nullptr);
startOffset = std::ftell(file);
if (!write)
{
u8 header[sizeof(RZipHeader)];
@@ -39,7 +36,7 @@ bool RZipFile::Open(const std::string& path, bool write)
|| std::fread(&maxChunkSize, sizeof(maxChunkSize), 1, file) != 1
|| std::fread(&size, sizeof(size), 1, file) != 1)
{
Close();
std::fseek(file, startOffset, SEEK_SET);
return false;
}
// savestates created on 32-bit platforms used to have a 32-bit size
@@ -59,11 +56,24 @@ bool RZipFile::Open(const std::string& path, bool write)
|| std::fwrite(&maxChunkSize, sizeof(maxChunkSize), 1, file) != 1
|| std::fwrite(&size, sizeof(size), 1, file) != 1)
{
Close();
std::fseek(file, startOffset, SEEK_SET);
return false;
}
}
this->write = write;
this->file = file;
return true;
}
bool RZipFile::Open(const std::string& path, bool write)
{
FILE *f = nowide::fopen(path.c_str(), write ? "wb" : "rb");
if (f == nullptr)
return false;
if (!Open(f, write)) {
Close();
return false;
}
return true;
}
@@ -73,7 +83,7 @@ void RZipFile::Close()
{
if (write)
{
std::fseek(file, sizeof(RZipHeader) + sizeof(maxChunkSize), SEEK_SET);
std::fseek(file, startOffset + sizeof(RZipHeader) + sizeof(maxChunkSize), SEEK_SET);
std::fwrite(&size, sizeof(size), 1, file);
}
std::fclose(file);
+2
View File
@@ -28,6 +28,7 @@ public:
~RZipFile() { Close(); }
bool Open(const std::string& path, bool write);
bool Open(FILE *file, bool write);
void Close();
size_t Size() const { return size; }
size_t Read(void *data, size_t length);
@@ -42,4 +43,5 @@ private:
u32 chunkSize = 0;
u32 chunkIndex = 0;
bool write = false;
long startOffset = 0;
};
+17
View File
@@ -0,0 +1,17 @@
target_sources(${PROJECT_NAME} PRIVATE
audiostream.h)
if(NOT LIBRETRO)
target_sources(${PROJECT_NAME} PRIVATE
audiobackend_alsa.cpp
audiobackend_coreaudio.cpp
audiobackend_directsound.cpp
audiobackend_libao.cpp
audiobackend_null.cpp
audiobackend_oboe.cpp
audiobackend_omx.cpp
audiobackend_oss.cpp
audiobackend_pulseaudio.cpp
audiobackend_sdl2.cpp
audiostream.cpp)
endif()
+1 -1
View File
@@ -20,7 +20,7 @@ public:
{
snd_pcm_hw_params_t *params;
std::string device = cfgLoadStr("alsa", "device", "");
std::string device = config::loadStr("alsa", "device");
int rc = -1;
if (!device.empty() && device != "auto") {
+2
View File
@@ -9,6 +9,7 @@
#include <thread>
#include "stdclass.h"
#include "windows/comptr.h"
#include "oslib/oslib.h"
HWND getNativeHwnd();
#define verifyc(x) verify(!FAILED(x))
@@ -46,6 +47,7 @@ class DirectSoundBackend : public AudioBackend
void audioThreadMain()
{
ThreadName _("FlyDirectSound");
audioThreadRunning = true;
while (true)
{
+17 -10
View File
@@ -1,5 +1,5 @@
#include "audiostream.h"
#include "oslib/i18n.h"
#include <chrono>
#include <thread>
@@ -9,7 +9,7 @@ class NullAudioBackend : public AudioBackend
public:
NullAudioBackend()
: AudioBackend("null", "No Audio") {}
: AudioBackend("null", Tnop("No Audio")) {}
bool init() override
{
@@ -19,17 +19,20 @@ public:
u32 push(const void* frame, u32 samples, bool wait) override
{
if (wait)
if (wait && last_time.time_since_epoch() != the_clock::duration::zero())
{
if (last_time.time_since_epoch() != the_clock::duration::zero())
{
auto fduration = std::chrono::nanoseconds(1000000000L * samples / 44100);
auto duration = fduration - (the_clock::now() - last_time);
auto fduration = std::chrono::nanoseconds(1'000'000'000LL * samples / 44100);
auto duration = fduration - (the_clock::now() - last_time);
if (duration > std::chrono::nanoseconds::zero())
std::this_thread::sleep_for(duration);
last_time += fduration;
}
else
if (duration < -std::chrono::milliseconds(67))
// if ~4 frames ahead, reset time (fast forward detection)
last_time = the_clock::now();
else
last_time += fduration;
}
else {
last_time = the_clock::now();
}
return 1;
}
@@ -45,6 +48,10 @@ public:
return samples;
}
std::string getName() const override {
return i18n::Ts(name);
}
private:
the_clock::time_point last_time;
};
+10 -3
View File
@@ -19,12 +19,13 @@
#ifdef USE_OBOE
#include "audiostream.h"
#include "cfg/option.h"
#include "stdclass.h"
#include "oslib/i18n.h"
#include <oboe/Oboe.h>
#include <vector>
#include <algorithm>
#include <atomic>
#include <memory>
#include "stdclass.h"
class OboeBackend : AudioBackend
{
@@ -77,7 +78,7 @@ class OboeBackend : AudioBackend
public:
OboeBackend()
: AudioBackend("Oboe", "Automatic AAudio / OpenSL selection"), audioCallback(this), errorCallback(this) {}
: AudioBackend("Oboe", Tnop("Automatic AAudio / OpenSL selection")), audioCallback(this), errorCallback(this) {}
bool init() override
{
@@ -91,6 +92,7 @@ public:
->setFormat(oboe::AudioFormat::I16)
->setChannelCount(oboe::ChannelCount::Stereo)
->setSampleRate(44100)
->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::High)
->setFramesPerCallback(SAMPLE_COUNT)
->setDataCallback(&audioCallback)
->setErrorCallback(&errorCallback)
@@ -175,7 +177,7 @@ public:
}
recordStream->requestStart();
NOTICE_LOG(AUDIO, "Oboe recorder started. stream capacity: %d frames",
stream->getBufferCapacityInFrames());
recordStream->getBufferCapacityInFrames());
return true;
}
@@ -194,6 +196,11 @@ public:
}
return std::max(0, result.value());
}
std::string getName() const override {
return i18n::Ts(name);
}
};
static OboeBackend oboeBackend;
+76 -41
View File
@@ -10,29 +10,87 @@ class OSSAudioBackend : public AudioBackend
int audioFD = -1;
int recordFD = -1;
static int openDevice(int flags)
{
const char* path = "/dev/dsp";
int fd = open(path, flags);
if (fd < 0)
ERROR_LOG(AUDIO, "OSS: open(%s) failed: %s", path, strerror(errno));
return fd;
}
static bool setRate(int fd, int rate)
{
int tmp = rate;
if (ioctl(fd, SNDCTL_DSP_SPEED, &tmp) < 0)
{
ERROR_LOG(AUDIO, "OSS: ioctl(SNDCTL_DSP_SPEED) failed: %s", strerror(errno));
return false;
}
if (tmp != rate)
{
ERROR_LOG(AUDIO, "OSS: sample rate unsupported: %d => %d", rate, tmp);
return false;
}
return true;
}
static bool setChannels(int fd, int channels)
{
int tmp = channels;
if (ioctl(fd, SNDCTL_DSP_CHANNELS, &tmp) < 0)
{
ERROR_LOG(AUDIO, "OSS: ioctl(SNDCTL_DSP_CHANNELS) failed: %s", strerror(errno));
return false;
}
if (tmp != channels)
{
ERROR_LOG(AUDIO, "OSS: channels unsupported: %d => %d", channels, tmp);
return false;
}
return true;
}
static bool setFormat(int fd, int format)
{
int tmp = format;
if (ioctl(fd, SNDCTL_DSP_SETFMT, &tmp) < 0)
{
ERROR_LOG(AUDIO, "OSS: ioctl(SNDCTL_DSP_SETFMT) failed: %s", strerror(errno));
return false;
}
if (tmp != format)
{
ERROR_LOG(AUDIO, "OSS: sample format unsupported: %#.8x => %#.8x", format, tmp);
return false;
}
return true;
}
public:
OSSAudioBackend()
: AudioBackend("oss", "Open Sound System") {}
bool init() override
{
audioFD = open("/dev/dsp", O_WRONLY);
if (audioFD < 0)
audioFD = openDevice(O_WRONLY);
if (audioFD < 0 || !setRate(audioFD, 44100) || !setChannels(audioFD, 2) || !setFormat(audioFD, AFMT_S16_LE))
{
WARN_LOG(AUDIO, "Couldn't open /dev/dsp.");
term();
return false;
}
INFO_LOG(AUDIO, "sound enabled, dsp opened for write");
int tmp=44100;
int err_ret;
err_ret=ioctl(audioFD,SNDCTL_DSP_SPEED,&tmp);
INFO_LOG(AUDIO, "set Frequency to %i, return %i (rate=%i)", 44100, err_ret, tmp);
int channels=2;
err_ret=ioctl(audioFD, SNDCTL_DSP_CHANNELS, &channels);
INFO_LOG(AUDIO, "set dsp to stereo (%i => %i)", channels, err_ret);
int format=AFMT_S16_LE;
err_ret=ioctl(audioFD, SNDCTL_DSP_SETFMT, &format);
INFO_LOG(AUDIO, "set dsp to %s audio (%i/%i => %i)", "16bits signed", AFMT_S16_LE, format, err_ret);
return true;
}
@@ -54,34 +112,11 @@ public:
bool initRecord(u32 sampling_freq) override
{
recordFD = open("/dev/dsp", O_RDONLY);
if (recordFD < 0)
recordFD = openDevice(O_RDONLY);
if (recordFD < 0 || !setRate(recordFD, sampling_freq) || !setChannels(recordFD, 1) || !setFormat(recordFD, AFMT_S16_NE /* Native 16 bits */ ))
{
INFO_LOG(AUDIO, "OSS: can't open default audio capture device");
return false;
}
int tmp = AFMT_S16_NE; // Native 16 bits
if (ioctl(recordFD, SNDCTL_DSP_SETFMT, &tmp) == -1 || tmp != AFMT_S16_NE)
{
INFO_LOG(AUDIO, "OSS: can't set sample format");
close(recordFD);
recordFD = -1;
return false;
}
tmp = 1;
if (ioctl(recordFD, SNDCTL_DSP_CHANNELS, &tmp) == -1)
{
INFO_LOG(AUDIO, "OSS: can't set channel count");
close(recordFD);
recordFD = -1;
return false;
}
tmp = sampling_freq;
if (ioctl(recordFD, SNDCTL_DSP_SPEED, &tmp) == -1)
{
INFO_LOG(AUDIO, "OSS: can't set sample rate");
close(recordFD);
recordFD = -1;
termRecord();
return false;
}
+1 -1
View File
@@ -66,7 +66,7 @@ class SDLAudioBackend : AudioBackend
public:
SDLAudioBackend()
: AudioBackend("sdl2", "Simple DirectMedia Layer 2 Audio") {}
: AudioBackend("sdl2", "Simple DirectMedia Layer 2") {}
bool init() override
{
+23 -3
View File
@@ -1,5 +1,8 @@
#include "audiostream.h"
#include "cfg/option.h"
#include "emulator.h"
static void registerForEvents();
struct SoundFrame { s16 l; s16 r; };
@@ -32,7 +35,7 @@ AudioBackend *AudioBackend::getBackend(const std::string& slug)
autoBackend = sdlBackend;
if (autoBackend == nullptr)
autoBackend = backends->front();
INFO_LOG(AUDIO, "Auto-selected audio backend \"%s\" (%s).", autoBackend->slug.c_str(), autoBackend->name.c_str());
INFO_LOG(AUDIO, "Auto-selected audio backend \"%s\" (%s).", autoBackend->slug.c_str(), autoBackend->getName().c_str());
return autoBackend;
}
@@ -60,6 +63,7 @@ void WriteSample(s16 r, s16 l)
void InitAudio()
{
registerForEvents();
TermAudio();
std::string slug = config::AudioBackend;
@@ -71,7 +75,7 @@ void InitAudio()
}
if (currentBackend != nullptr)
{
INFO_LOG(AUDIO, "Initializing audio backend \"%s\" (%s)...", currentBackend->slug.c_str(), currentBackend->name.c_str());
INFO_LOG(AUDIO, "Initializing audio backend \"%s\" (%s)...", currentBackend->slug.c_str(), currentBackend->getName().c_str());
if (!currentBackend->init())
{
currentBackend = nullptr;
@@ -110,7 +114,7 @@ void TermAudio()
StopAudioRecording();
audio_recording_started = rec_started;
currentBackend->term();
INFO_LOG(AUDIO, "Terminating audio backend \"%s\" (%s)...", currentBackend->slug.c_str(), currentBackend->name.c_str());
INFO_LOG(AUDIO, "Terminating audio backend \"%s\" (%s)...", currentBackend->slug.c_str(), currentBackend->getName().c_str());
currentBackend = nullptr;
}
@@ -138,3 +142,19 @@ void StopAudioRecording()
currentBackend->termRecord();
audio_recording_started = false;
}
static void registerForEvents()
{
static bool done;
if (done)
return;
done = true;
// Empty the audio buffer when loading a state or terminating the game
const auto& callback = [](Event, void *) {
writePtr = 0;
};
EventManager::listen(Event::Terminate, callback);
EventManager::listen(Event::LoadState, callback);
}
+2 -1
View File
@@ -35,7 +35,7 @@ public:
virtual void termRecord() {}
std::string slug;
std::string name;
virtual std::string getName() const { return name; }
static size_t getCount() { return backends == nullptr ? 0 : backends->size(); }
static AudioBackend *getBackend(size_t index) { return backends == nullptr ? nullptr : (*backends)[index]; }
@@ -46,6 +46,7 @@ protected:
: slug(slug), name(name) {
registerAudioBackend(this);
}
std::string name;
private:
static void registerAudioBackend(AudioBackend *backend)
+15 -10
View File
@@ -15,12 +15,8 @@
//HOST_CPU
#define CPU_X86 0x20000001
#define CPU_ARM 0x20000002
#define CPU_MIPS 0x20000003
#define CPU_ARM64 0x20000003
#define CPU_X64 0x20000004
#define CPU_GENERIC 0x20000005 //used for pnacl, emscripten, etc
#define CPU_PPC 0x20000006
#define CPU_PPC64 0x20000007
#define CPU_ARM64 0x20000008
//FEAT_SHREC, FEAT_AREC, FEAT_DSPREC
#define DYNAREC_NONE 0x40000001
@@ -36,10 +32,19 @@
#define HOST_CPU CPU_ARM
#elif defined(__aarch64__) || defined(_M_ARM64)
#define HOST_CPU CPU_ARM64
#elif defined(__mips__)
#define HOST_CPU CPU_MIPS
#else
#define HOST_CPU CPU_GENERIC
#error Unsupported architecture
#endif
#if defined(__APPLE__)
#include "TargetConditionals.h"
#if TARGET_OS_SIMULATOR
// iOS simulator
#define TARGET_NO_REC
#endif
#if defined(TARGET_MAC) && HOST_CPU == CPU_ARM64
#define TARGET_ARM_MAC
#endif
#endif
#if defined(TARGET_NO_REC)
@@ -93,14 +98,14 @@
#ifdef _WIN32
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
#define TARGET_UWP
#define TARGET_UWP 1
#endif
#ifdef HAVE_D3D11
#define USE_DX11
#endif
#endif
#if !defined(LIBRETRO) && !defined(TARGET_NO_EXCEPTIONS)
#if !defined(LIBRETRO)
#define USE_GGPO
#endif
+12
View File
@@ -0,0 +1,12 @@
target_sources(${PROJECT_NAME} PRIVATE
option.h)
if(NOT LIBRETRO)
target_sources(${PROJECT_NAME} PRIVATE
cfg.cpp
cfg.h
cl.cpp
ini.cpp
ini.h
option.cpp)
endif()
+62 -63
View File
@@ -1,37 +1,33 @@
#include "cfg.h"
#include "ini.h"
#include "stdclass.h"
#include <cerrno>
namespace config
{
static std::string cfgPath;
static bool save_config = true;
static bool autoSave = true;
static bool autoSaving = true;
static IniFile cfgdb;
static emucfg::ConfigFile cfgdb;
static void saveConfigFile()
static void saveFile()
{
FILE* cfgfile = nowide::fopen(cfgPath.c_str(), "wt");
if (!cfgfile)
{
if (!cfgfile) {
WARN_LOG(COMMON, "Error: Unable to open file '%s' for saving", cfgPath.c_str());
}
else
{
else {
cfgdb.save(cfgfile);
std::fclose(cfgfile);
}
}
void cfgSaveStr(const std::string& section, const std::string& key, const std::string& value)
{
cfgdb.set(section, key, value);
if (save_config && autoSave)
saveConfigFile();
static void autoSave() {
if (autoSaving)
saveFile();
}
bool cfgOpen()
bool open()
{
if (get_writable_config_path("").empty())
// Config dir not set (android onboarding)
@@ -41,9 +37,9 @@ bool cfgOpen()
std::string config_path_read = get_readonly_config_path(filename);
cfgPath = get_writable_config_path(filename);
FILE* cfgfile = nowide::fopen(config_path_read.c_str(), "r");
if(cfgfile != NULL) {
cfgdb.parse(cfgfile);
FILE* cfgfile = nowide::fopen(config_path_read.c_str(), "rt");
if (cfgfile != nullptr) {
cfgdb.load(cfgfile);
std::fclose(cfgfile);
}
else
@@ -55,78 +51,81 @@ bool cfgOpen()
{
// Config file didn't exist
INFO_LOG(COMMON, "Creating new empty config file at '%s'", cfgPath.c_str());
saveConfigFile();
}
else
{
// There was some other error (may be a permissions problem or something like that)
save_config = false;
saveFile();
}
}
return true;
}
std::string cfgLoadStr(const std::string& section, const std::string& key, const std::string& def)
{
return cfgdb.get(section, key, def);
void saveStr(const std::string& section, const std::string& key, const std::string& value) {
cfgdb.set(section, key, value);
autoSave();
}
void cfgSaveInt(const std::string& section, const std::string& key, s32 value)
{
cfgSaveStr(section, key, std::to_string(value));
std::string loadStr(const std::string& section, const std::string& key, const std::string& def) {
return cfgdb.getString(section, key, def);
}
s32 cfgLoadInt(const std::string& section, const std::string& key, s32 def)
{
return cfgdb.get_int(section, key, def);
void saveInt(const std::string& section, const std::string& key, int value) {
cfgdb.set(section, key, value);
autoSave();
}
int64_t cfgLoadInt64(const std::string& section, const std::string& key, int64_t def) {
return cfgdb.get_int64(section, key, def);
}
void cfgSaveInt64(const std::string& section, const std::string& key, int64_t value) {
cfgdb.set_int64(section, key, value);
int loadInt(const std::string& section, const std::string& key, int def) {
return cfgdb.getInt(section, key, def);
}
void cfgSaveBool(const std::string& section, const std::string& key, bool value)
{
cfgSaveStr(section, key, value ? "yes" : "no");
int64_t loadInt64(const std::string& section, const std::string& key, int64_t def) {
return cfgdb.getInt64(section, key, def);
}
void saveInt64(const std::string& section, const std::string& key, int64_t value) {
cfgdb.set(section, key, value);
autoSave();
}
bool cfgLoadBool(const std::string& section, const std::string& key, bool def)
{
return cfgdb.get_bool(section, key, def);
void saveBool(const std::string& section, const std::string& key, bool value) {
cfgdb.set(section, key, value);
autoSave();
}
void cfgSetVirtual(const std::string& section, const std::string& key, const std::string& value)
{
bool loadBool(const std::string& section, const std::string& key, bool def) {
return cfgdb.getBool(section, key, def);
}
void setTransient(const std::string& section, const std::string& key, const std::string& value) {
cfgdb.set(section, key, value, true);
}
bool cfgIsVirtual(const std::string& section, const std::string& key)
{
return cfgdb.is_virtual(section, key);
bool isTransient(const std::string& section, const std::string& key) {
return cfgdb.isTransient(section, key);
}
bool cfgHasSection(const std::string& section)
{
return cfgdb.has_section(section);
bool hasSection(const std::string& section) {
return cfgdb.hasSection(section);
}
void cfgDeleteSection(const std::string& section)
{
cfgdb.delete_section(section);
void deleteSection(const std::string& section) {
cfgdb.deleteSection(section);
}
void cfgDeleteEntry(const std::string& section, const std::string& key)
{
cfgdb.delete_entry(section, key);
void deleteEntry(const std::string& section, const std::string& key) {
cfgdb.deleteEntry(section, key);
}
void cfgSetAutoSave(bool autoSave)
void setAutoSave(bool autoSaving)
{
::autoSave = autoSave;
if (autoSave)
saveConfigFile();
config::autoSaving = autoSaving;
if (autoSaving)
saveFile();
}
void saveFloat(const std::string& section, const std::string& key, float value) {
cfgdb.set(section, key, value);
autoSave();
}
float loadFloat(const std::string& section, const std::string& key, float def) {
return cfgdb.getFloat(section, key, def);
}
} // namespace config
+23 -17
View File
@@ -1,22 +1,28 @@
#pragma once
#include "types.h"
bool cfgOpen();
s32 cfgLoadInt(const std::string& section, const std::string& key, s32 def);
void cfgSaveInt(const std::string& section, const std::string& key, s32 value);
int64_t cfgLoadInt64(const std::string& section, const std::string& key, int64_t def);
void cfgSaveInt64(const std::string& section, const std::string& key, int64_t value);
std::string cfgLoadStr(const std::string& section, const std::string& key, const std::string& def);
void cfgSaveStr(const std::string& section, const std::string& key, const std::string& value);
void cfgSaveBool(const std::string& section, const std::string& key, bool value);
bool cfgLoadBool(const std::string& section, const std::string& key, bool def);
void cfgSetVirtual(const std::string& section, const std::string& key, const std::string& value);
bool cfgIsVirtual(const std::string& section, const std::string& key);
namespace config
{
void ParseCommandLine(int argc, char *argv[]);
bool open();
int loadInt(const std::string& section, const std::string& key, int def = 0);
void saveInt(const std::string& section, const std::string& key, int value);
int64_t loadInt64(const std::string& section, const std::string& key, int64_t def = 0);
void saveInt64(const std::string& section, const std::string& key, int64_t value);
std::string loadStr(const std::string& section, const std::string& key, const std::string& def = {});
void saveStr(const std::string& section, const std::string& key, const std::string& value);
bool loadBool(const std::string& section, const std::string& key, bool def = false);
void saveBool(const std::string& section, const std::string& key, bool value);
float loadFloat(const std::string& section, const std::string& key, float def = 0.f);
void saveFloat(const std::string& section, const std::string& key, float value);
void setTransient(const std::string& section, const std::string& key, const std::string& value);
bool isTransient(const std::string& section, const std::string& key);
void cfgSetAutoSave(bool autoSave);
bool cfgHasSection(const std::string& section);
void cfgDeleteSection(const std::string& section);
void cfgDeleteEntry(const std::string& section, const std::string& key);
void parseCommandLine(int argc, const char * const argv[]);
void setAutoSave(bool autoSave);
bool hasSection(const std::string& section);
void deleteSection(const std::string& section);
void deleteEntry(const std::string& section, const std::string& key);
}
+91 -119
View File
@@ -1,143 +1,115 @@
/*
Command line parsing
*/
Copyright 2025 flyinghead
This file is part of Flycast.
Flycast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Flycast is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#include "cfg/cfg.h"
#include "stdclass.h"
#include <cstdio>
#include <cstring>
#include "cfg/cfg.h"
#include "stdclass.h"
static int setconfig(char *arg[], int cl)
namespace config
{
int rv=0;
if (cl < 1)
static void usage(const char *exe)
{
fprintf(stderr, "Usage: %s [option]... [<rom path>]\n", exe);
fprintf(stderr, "Options:\n");
fprintf(stderr, "-config section:key=value,... set a transient config value.\n");
fprintf(stderr, " Transient config values won't be saved to emu.cfg.\n");
fprintf(stderr, "-help display this help\n");
}
static void parseConfigOption(const std::string& str)
{
size_t pos = 0;
while (pos < str.length())
{
WARN_LOG(COMMON, "-config : invalid number of parameters, format is section:key=value,section:key=value,...");
return rv;
size_t comma = str.find(',', pos);
if (comma == str.npos)
comma = str.length();
std::string option = str.substr(pos, comma - pos);
size_t colpos = option.find(':');
size_t eqpos = option.npos;
if (colpos != option.npos)
{
std::string section = option.substr(0, colpos);
eqpos = option.find('=', colpos);
if (eqpos != option.npos)
{
std::string key = option.substr(colpos + 1, eqpos - (colpos + 1));
std::string value = option.substr(eqpos + 1);
setTransient(section, key, value);
DEBUG_LOG(COMMON, "-config [%s] %s = %s", section.c_str(), key.c_str(), value.c_str());
}
}
if (colpos == option.npos || eqpos == option.npos) {
WARN_LOG(COMMON, "Invalid -config option '%s'. Format is: -config section:key=value,...", str.c_str());
return;
}
pos = comma + 1;
}
std::string value(arg[1]);
for(;;)
{
auto seppos = value.find(':');
if (seppos == std::string::npos)
{
WARN_LOG(COMMON, "-config : invalid parameter %s, format is section:key=value,section:key=value,...", value.c_str());
break;
}
auto eqpos = value.find('=', seppos);
if (eqpos == std::string::npos)
{
WARN_LOG(COMMON, "-config : invalid parameter %s, format is section:key=value,section:key=value,...", value.c_str());
break;
}
auto commapos = value.find(',', eqpos);
std::string sect = trim_ws(value.substr(0, seppos));
std::string key = trim_ws(value.substr(seppos + 1, eqpos - seppos - 1));
auto endofcurrent = (commapos == std::string::npos) ? value.size() : commapos;
std::string next = (commapos == std::string::npos) ? "" : trim_ws(value.substr(endofcurrent + 1, value.size() - endofcurrent));
value = trim_ws(value.substr(eqpos + 1, endofcurrent - eqpos - 1));
if (sect.empty() || key.empty())
{
WARN_LOG(COMMON, "-config : invalid parameter, format is section:key=value,section:key=value,...");
break;
}
INFO_LOG(COMMON, "Virtual cfg %s:%s=%s", sect.c_str(), key.c_str(), value.c_str());
cfgSetVirtual(sect, key, value);
if (commapos == std::string::npos)
rv++;
if (commapos != std::string::npos)
{
value = next;
continue;
}
else if (cl>=3 && strcmp(arg[2],",")==0)
{
cl-=2;
arg+=2;
rv++;
continue;
}
else
break;
}
return rv;
}
static int showhelp()
{
printf("Usage: flycast [OPTION]... [CONTENT]\n\n");
printf("Options:\n");
printf("-config section:key=value add a virtual config value;\n");
printf(" virtual config values won't be saved to the .cfg file\n");
printf(" unless a different value is written to them\n");
printf("-help display this help\n");
exit(0);
return 0;
}
void ParseCommandLine(int argc,char* argv[])
void parseCommandLine(int argc, const char * const argv[])
{
settings.content.path.clear();
int cl=argc-2;
char** arg=argv+1;
while(cl>=0)
const char *exe = argv[0];
for (int i = 1; i < argc; i++)
{
if (stricmp(*arg,"-help")==0 || stricmp(*arg,"--help")==0)
{
showhelp();
if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) {
usage(exe);
exit(0);
}
else if (stricmp(*arg,"-config")==0 || stricmp(*arg,"--config")==0)
if (!strcmp(argv[i], "-config") || !strcmp(argv[i], "--config"))
{
int as=setconfig(arg,cl);
cl-=as;
arg+=as;
if (i < argc - 1)
parseConfigOption(argv[++i]);
continue;
}
#if defined(__APPLE__)
else if (!strncmp(*arg, "-NSDocumentRevisions", 20))
// macOS
if (!strncmp(argv[i], "-NSDocumentRevisions", 20)) {
i++;
continue;
}
if (argv[i][0] == '-') {
WARN_LOG(COMMON, "Ignoring unknown command line option '%s'", argv[i]);
continue;
}
std::string extension = get_file_extension(argv[i]);
if (extension == "cdi" || extension == "chd"
|| extension == "gdi"|| extension == "cue")
{
arg++;
cl--;
INFO_LOG(COMMON, "Using '%s' as CD image", argv[i]);
settings.content.path = argv[i];
}
#endif
else if ((*arg)[0] == '-')
else if (extension == "elf")
{
WARN_LOG(COMMON, "Ignoring unknown command line option '%s'", *arg);
INFO_LOG(COMMON, "Using '%s' as reios elf file", argv[i]);
setTransient("config", "bios.UseReios", "yes");
settings.content.path = argv[i];
}
else
{
char* extension = strrchr(*arg, '.');
if (extension
&& (stricmp(extension, ".cdi") == 0 || stricmp(extension, ".chd") == 0
|| stricmp(extension, ".gdi") == 0 || stricmp(extension, ".cue") == 0))
{
INFO_LOG(COMMON, "Using '%s' as cd image", *arg);
settings.content.path = *arg;
}
else if (extension && stricmp(extension, ".elf") == 0)
{
INFO_LOG(COMMON, "Using '%s' as reios elf file", *arg);
cfgSetVirtual("config", "bios.UseReios", "yes");
settings.content.path = *arg;
}
else
{
INFO_LOG(COMMON, "Using '%s' as rom", *arg);
settings.content.path = *arg;
}
else {
INFO_LOG(COMMON, "Using '%s' as rom", argv[i]);
settings.content.path = argv[i];
}
arg++;
cl--;
if (i < argc - 1)
WARN_LOG(COMMON, "Rest of command line ignored: '%s'...", argv[i + 1]);
break;
}
}
} // namespace config
+268 -244
View File
@@ -1,298 +1,322 @@
/*
Copyright 2025 flyinghead
This file is part of Flycast.
Flycast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Flycast is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#include "ini.h"
#include "types.h"
#include <sstream>
#include "stdclass.h"
namespace emucfg {
namespace config {
/* ConfigEntry */
const std::string& ConfigEntry::get_string() const
const IniFile::Entry *IniFile::getEntry(const std::string& sectionName, const std::string& name) const
{
return this->value;
auto it = sections.find(sectionName);
if (it == sections.end())
return nullptr;
const Section& section = it->second;
auto it2 = section.entries.find(name);
if (it2 == section.entries.end())
return nullptr;
return &it2->second;
}
int ConfigEntry::get_int()
const std::string *IniFile::getRaw(const std::string& section, const std::string& name) const
{
if (strstr(this->value.c_str(), "0x") != NULL)
{
return (int)strtoul(this->value.c_str(), NULL, 16);
}
const Entry *entry = getEntry(section, name);
if (entry == nullptr)
return nullptr;
if (entry->transient)
return &entry->transientValue;
else
{
return atoi(this->value.c_str());
}
return &entry->value;
}
int64_t ConfigEntry::get_int64()
const std::string& IniFile::getString(const std::string& section, const std::string& entry, const std::string& defaultValue) const
{
int base = 10;
if (strstr(this->value.c_str(), "0x") != nullptr)
base = 16;
return (int64_t)strtoll(this->value.c_str(), nullptr, base);
const std::string *pValue = getRaw(section, entry);
if (pValue == nullptr)
return defaultValue;
else
return *pValue;
}
bool ConfigEntry::get_bool()
bool IniFile::getBool(const std::string& section, const std::string& entry, bool defaultValue) const
{
if (stricmp(this->value.c_str(), "yes") == 0 ||
stricmp(this->value.c_str(), "true") == 0 ||
stricmp(this->value.c_str(), "on") == 0 ||
stricmp(this->value.c_str(), "1") == 0)
{
const std::string *pValue = getRaw(section, entry);
if (pValue == nullptr)
return defaultValue;
if (!stricmp("yes", pValue->c_str())
|| !stricmp("true", pValue->c_str())
|| !stricmp("on", pValue->c_str())
|| !stricmp("1", pValue->c_str()))
return true;
}
else
{
return false;
}
static bool hasHexPrefix(const std::string& s)
{
size_t pos = 0;
while (pos < s.length() - 1 && std::isspace((int8_t)s[pos]))
pos++;
if (pos + 1 >= s.length())
return false;
return (s[pos] == '0' && (s[pos + 1] == 'x' || s[pos + 1] == 'X'));
}
int IniFile::getInt(const std::string& section, const std::string& entry, int defaultValue) const
{
const std::string *pValue = getRaw(section, entry);
if (pValue == nullptr)
return defaultValue;
std::istringstream ss(*pValue);
ss.imbue(std::locale::classic());
if (hasHexPrefix(*pValue))
ss.setf(std::ios_base::hex, std::ios_base::basefield);
else
ss.setf(std::ios_base::dec, std::ios_base::basefield);
unsigned value = defaultValue;
ss >> value;
return (int)value;
}
int64_t IniFile::getInt64(const std::string& section, const std::string& entry, int64_t defaultValue) const
{
const std::string *pValue = getRaw(section, entry);
if (pValue == nullptr)
return defaultValue;
std::istringstream ss(*pValue);
ss.imbue(std::locale::classic());
if (hasHexPrefix(*pValue))
ss.setf(std::ios_base::hex, std::ios_base::basefield);
else
ss.setf(std::ios_base::dec, std::ios_base::basefield);
int64_t value = defaultValue;
ss >> value;
return value;
}
float IniFile::getFloat(const std::string& section, const std::string& entry, float defaultValue) const
{
const std::string *pValue = getRaw(section, entry);
if (pValue == nullptr || pValue->empty())
return defaultValue;
std::istringstream ss(*pValue);
ss.imbue(std::locale::classic());
float value = defaultValue;
ss >> value;
return value;
}
void IniFile::setRaw(const std::string& sectionName, const std::string& entryName, const std::string& value, bool transient)
{
Section& section = sections[sectionName];
Entry& entry = section.entries[entryName];
if (entry.name.empty())
entry.name = entryName;
if (transient) {
entry.transientValue = value;
entry.transient = true;
}
else {
entry.value = value;
}
}
/* ConfigSection */
bool ConfigSection::has_entry(const std::string& name)
static std::string handleEscapeSeq(const std::string& s)
{
return (this->entries.count(name) == 1);
}
ConfigEntry* ConfigSection::get_entry(const std::string& name)
{
if(this->has_entry(name))
std::string ret;
ret.reserve(s.length());
for (size_t i = 0; i < s.length(); i++)
{
return &this->entries[name];
}
return NULL;
}
void ConfigSection::set(const std::string& name, const std::string& value)
{
ConfigEntry new_entry = { value };
this->entries[name] = new_entry;
}
void ConfigSection::delete_entry(const std::string& name)
{
this->entries.erase(name);
}
/* ConfigFile */
ConfigSection* ConfigFile::add_section(const std::string& name, bool is_virtual)
{
ConfigSection new_section;
if (is_virtual)
{
this->virtual_sections.insert(std::make_pair(name, new_section));
return &this->virtual_sections[name];
}
this->sections.insert(std::make_pair(name, new_section));
return &this->sections[name];
}
bool ConfigFile::has_section(const std::string& name)
{
return (this->virtual_sections.count(name) == 1 || this->sections.count(name) == 1);
}
bool ConfigFile::has_entry(const std::string& section_name, const std::string& entry_name)
{
ConfigSection* section = this->get_section(section_name, true);
if ((section != NULL) && section->has_entry(entry_name))
{
return true;
}
section = this->get_section(section_name, false);
return ((section != NULL) && section->has_entry(entry_name));
}
ConfigSection* ConfigFile::get_section(const std::string& name, bool is_virtual)
{
if(is_virtual)
{
if (this->virtual_sections.count(name) == 1)
char c = s[i];
if (c == '\\' && i < s.length() - 1)
{
return &this->virtual_sections[name];
switch (s[++i])
{
case 'n':
ret += '\n';
break;
case 't':
ret += '\t';
break;
case 'r':
ret += '\r';
break;
case 'f':
ret += '\f';
break;
case '\\':
ret += '\\';
break;
default:
WARN_LOG(COMMON, "Unrecognized escape sequence [\\%c] in [%s]", s[i], s.c_str());
ret += '\\';
--i;
break;
}
}
else {
ret += c;
}
}
else
return ret;
}
void IniFile::load(const std::string& data, bool cEscape)
{
std::istringstream fss(data);
int cline = 1;
std::string curSection;
for (std::string line; std::getline(fss, line); cline++)
{
if (this->sections.count(name) == 1)
size_t pos = 0;
while (pos < line.length() && std::isspace((int8_t)line[pos]))
pos++;
if (pos == line.length() || line[pos] == ';')
// Ignore empty lines and comments
continue;
if (line[pos] == '[')
{
return &this->sections[name];
// Section
size_t end = line.find(']', ++pos);
if (end == line.npos) {
WARN_LOG(COMMON, "Missing ']' character - ignoring line %d: %s", cline, line.c_str());
continue;
}
curSection = line.substr(pos, end - pos);
if (cEscape)
curSection = handleEscapeSeq(curSection);
}
else
{
// Entry
pos = line.find('=', pos);
if (pos == line.npos) {
WARN_LOG(COMMON, "Malformed entry - ignoring line %d: %s", cline, line.c_str());
continue;
}
std::string entry = trim_ws(line.substr(0, pos), " \t");
if (entry.empty()) {
WARN_LOG(COMMON, "Invalid empty entry name - ignoring line %d: %s", cline, line.c_str());
continue;
}
std::string value = line.substr(pos + 1);
// Space characters before and after the equal sign are for readability, and not part of the entry name or value
if (value[0] == ' ')
value = value.substr(1);
if (value[0] == '"')
{
// quoted value
size_t end = value.rfind('"');
if (end == value.npos || end == 0)
end = value.length();
value = value.substr(1, end - 1);
}
if (cEscape) {
entry = handleEscapeSeq(entry);
value = handleEscapeSeq(value);
}
set(curSection, entry, value);
}
}
return NULL;
}
ConfigEntry* ConfigFile::get_entry(const std::string& section_name, const std::string& entry_name)
void IniFile::load(FILE *file, bool cEscape)
{
ConfigSection* section = this->get_section(section_name, true);
if(section != NULL && section->has_entry(entry_name))
std::string data;
for (;;)
{
return section->get_entry(entry_name);
}
section = this->get_section(section_name, false);
if(section != NULL)
{
return section->get_entry(entry_name);
}
return NULL;
}
std::string ConfigFile::get(const std::string& section_name, const std::string& entry_name, const std::string& default_value)
{
ConfigEntry* entry = this->get_entry(section_name, entry_name);
if (entry == NULL)
{
return default_value;
}
else
{
return entry->get_string();
}
}
int ConfigFile::get_int(const std::string& section_name, const std::string& entry_name, int default_value)
{
ConfigEntry* entry = this->get_entry(section_name, entry_name);
if (entry == NULL)
{
return default_value;
}
else
{
return entry->get_int();
}
}
int64_t ConfigFile::get_int64(const std::string& section_name, const std::string& entry_name, int64_t default_value)
{
ConfigEntry* entry = this->get_entry(section_name, entry_name);
if (entry == NULL)
{
return default_value;
}
else
{
return entry->get_int64();
}
}
bool ConfigFile::get_bool(const std::string& section_name, const std::string& entry_name, bool default_value)
{
ConfigEntry* entry = this->get_entry(section_name, entry_name);
if (entry == NULL)
{
return default_value;
}
else
{
return entry->get_bool();
}
}
void ConfigFile::set(const std::string& section_name, const std::string& entry_name, const std::string& value, bool is_virtual)
{
ConfigSection* section = this->get_section(section_name, is_virtual);
if(section == NULL)
{
section = this->add_section(section_name, is_virtual);
}
section->set(entry_name, value);
}
void ConfigFile::set_int(const std::string& section_name, const std::string& entry_name, int value, bool is_virtual)
{
std::stringstream str_value;
str_value << value;
this->set(section_name, entry_name, str_value.str(), is_virtual);
}
void ConfigFile::set_int64(const std::string& section_name, const std::string& entry_name, int64_t value, bool is_virtual)
{
std::stringstream str_value;
str_value << value;
this->set(section_name, entry_name, str_value.str(), is_virtual);
}
void ConfigFile::set_bool(const std::string& section_name, const std::string& entry_name, bool value, bool is_virtual)
{
std::string str_value = (value ? "yes" : "no");
this->set(section_name, entry_name, str_value, is_virtual);
}
void ConfigFile::parse(FILE* file)
{
if (file == nullptr)
return;
char line[512];
std::string section;
int cline = 0;
while (true)
{
if (std::fgets(line, sizeof(line), file) == nullptr)
char buffer[4096];
int n = fread(buffer, 1, sizeof(buffer), file);
if (n <= 0)
break;
cline++;
std::string s(line);
s = trim_ws(s, " \r\n");
if (s.empty())
continue;
if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']')
{
section = s.substr(1, s.length() - 2);
continue;
}
auto eqpos = s.find('=');
if (eqpos == std::string::npos)
{
WARN_LOG(COMMON, "Malformed entry on config - ignoring line %d: %s", cline, s.c_str());
continue;
}
std::string property = trim_ws(s.substr(0, eqpos));
std::string value = trim_ws(s.substr(eqpos + 1));
if (value.length() >= 2 && value[0] == '"' && value[value.length() - 1] == '"')
value = value.substr(1, value.length() - 2);
set(section, property, value);
data += std::string(buffer, buffer + n);
}
load(data, cEscape);
}
void ConfigFile::save(FILE* file)
void IniFile::save(std::string& data) const
{
for (const auto& [section_name, section] : this->sections)
std::ostringstream ss;
for (const auto& [sectionName, section] : sections)
{
if (!section_name.empty())
std::fprintf(file, "[%s]\n", section_name.c_str());
for (const auto& [entry_name, entry] : section.entries)
bool sectionSaved = sectionName.empty();
for (const auto& [name, entry] : section.entries)
{
std::fprintf(file, "%s = %s\n", entry_name.c_str(), entry.get_string().c_str());
if (entry.transient && entry.value.empty())
// Don't save transient-only values
continue;
if (!sectionSaved) {
ss << '[' << sectionName << ']' << std::endl;
sectionSaved = true;
}
ss << name << " = " << entry.value << std::endl;
}
if (!section_name.empty())
std::fputc('\n', file);
ss << std::endl;
}
data = ss.str();
}
void ConfigFile::delete_section(const std::string& section_name) {
sections.erase(section_name);
virtual_sections.erase(section_name);
}
void ConfigFile::delete_entry(const std::string& section_name, const std::string& entry_name)
void IniFile::save(FILE *file) const
{
ConfigSection *section = get_section(section_name, false);
if (section != NULL)
section->delete_entry(entry_name);
std::string data;
save(data);
fwrite(data.c_str(), 1, data.length(), file);
}
bool ConfigFile::is_virtual(const std::string& section_name, const std::string& entry_name)
bool IniFile::hasSection(const std::string& section) const {
return sections.count(section) != 0;
}
bool IniFile::hasEntry(const std::string& section, const std::string& name) const {
return getEntry(section, name) != nullptr;
}
bool IniFile::isTransient(const std::string& section, const std::string& name) const
{
ConfigSection *section = get_section(section_name, true);
if (section == nullptr)
const Entry *entry = getEntry(section, name);
if (entry == nullptr)
return false;
return section->has_entry(entry_name);
else
return entry->transient;
}
} // namespace emucfg
void IniFile::deleteSection(const std::string& section) {
sections.erase(section);
}
void IniFile::deleteEntry(const std::string& sectionName, const std::string& entry)
{
auto it = sections.find(sectionName);
if (it == sections.end())
return;
Section& section = it->second;
section.entries.erase(entry);
}
std::vector<std::string> IniFile::getEntryNames(const std::string& sectionName) const
{
std::vector<std::string> v;
auto it = sections.find(sectionName);
if (it != sections.end())
{
const Section& section = it->second;
for (const auto& [name, entry] : section.entries)
v.push_back(name);
}
return v;
}
} // namespace config
+95 -49
View File
@@ -1,59 +1,105 @@
#pragma once
/*
Copyright 2025 flyinghead
This file is part of Flycast.
Flycast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Flycast is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstdio>
#include <map>
#include <string>
#include <cstdint>
#include <vector>
#include <locale>
#include <sstream>
namespace emucfg {
namespace config {
struct ConfigEntry {
std::string value;
const std::string& get_string() const;
int get_int();
bool get_bool();
int64_t get_int64();
class IniFile
{
public:
void load(FILE *file, bool cEscape = false);
void load(const std::string& data, bool cEscape = false);
void save(FILE *file) const;
void save(std::string& data) const;
bool hasSection(const std::string& section) const;
bool hasEntry(const std::string& section, const std::string& name) const;
bool isTransient(const std::string& section, const std::string& name) const;
void deleteSection(const std::string& section);
void deleteEntry(const std::string& section, const std::string& name);
template<typename T>
void set(const std::string& section, const std::string& entry, T value, bool transient = false) {
setRaw(section, entry, std::to_string(value), transient);
}
const std::string& getString(const std::string& section, const std::string& entry, const std::string& defaultValue = {}) const;
const std::string& get(const std::string& section, const std::string& entry, const std::string& defaultValue = {}) const {
return getString(section, entry, defaultValue);
}
bool getBool(const std::string& section, const std::string& entry, bool defaultValue = false) const;
int getInt(const std::string& section, const std::string& entry, int defaultValue = 0) const;
int64_t getInt64(const std::string& section, const std::string& entry, int64_t defaultValue = 0ll) const;
float getFloat(const std::string& section, const std::string& entry, float defaultValue = 0.f) const;
std::vector<std::string> getEntryNames(const std::string& section) const;
private:
struct Entry
{
std::string name;
std::string value;
std::string transientValue;
bool transient = false;
};
struct Section
{
std::string name;
std::map<std::string, Entry> entries;
};
const Entry *getEntry(const std::string& section, const std::string& entry) const;
const std::string *getRaw(const std::string& section, const std::string& name) const;
void setRaw(const std::string& section, const std::string& name, const std::string& value, bool transient);
std::map<std::string, Section> sections;
};
struct ConfigSection {
std::map<std::string, ConfigEntry> entries;
bool has_entry(const std::string& name);
void set(const std::string& name, const std::string& value);
void delete_entry(const std::string& name);
ConfigEntry* get_entry(const std::string& name);
};
struct ConfigFile {
private:
std::map<std::string, ConfigSection> sections;
std::map<std::string, ConfigSection> virtual_sections;
ConfigSection* add_section(const std::string& name, bool is_virtual);
ConfigSection* get_section(const std::string& name, bool is_virtual);
ConfigEntry* get_entry(const std::string& section_name, const std::string& entry_name);
public:
bool has_section(const std::string& name);
bool has_entry(const std::string& section_name, const std::string& entry_name);
bool is_virtual(const std::string& section_name, const std::string& entry_name);
void parse(FILE* file);
void save(FILE* file);
/* getting values */
std::string get(const std::string& section_name, const std::string& entry_name, const std::string& default_value = "");
int get_int(const std::string& section_name, const std::string& entry_name, int default_value = 0);
int64_t get_int64(const std::string& section_name, const std::string& entry_name, int64_t default_value = 0);
bool get_bool(const std::string& section_name, const std::string& entry_name, bool default_value = false);
/* setting values */
void set(const std::string& section_name, const std::string& entry_name, const std::string& value, bool is_virtual = false);
void set_int(const std::string& section_name, const std::string& entry_name, int value, bool is_virtual = false);
void set_int64(const std::string& section_name, const std::string& entry_name, int64_t value, bool is_virtual = false);
void set_bool(const std::string& section_name, const std::string& entry_name, bool value, bool is_virtual = false);
void delete_section(const std::string& section_name);
void delete_entry(const std::string& section_name, const std::string& entry_name);
};
} // namespace emucfg
template<>
inline void IniFile::set(const std::string& section, const std::string& entry, const std::string& value, bool transient) {
setRaw(section, entry, value, transient);
}
template<>
inline void IniFile::set(const std::string& section, const std::string& entry, std::string value, bool transient) {
setRaw(section, entry, value, transient);
}
template<>
inline void IniFile::set(const std::string& section, const std::string& entry, const char *value, bool transient) {
setRaw(section, entry, value, transient);
}
template<>
inline void IniFile::set(const std::string& section, const std::string& entry, bool value, bool transient) {
setRaw(section, entry, value ? "yes" : "no", transient);
}
template<>
inline void IniFile::set(const std::string& section, const std::string& entry, float value, bool transient)
{
std::ostringstream ss;
ss.imbue(std::locale::classic());
ss.precision(7);
ss << value;
setRaw(section, entry, ss.str(), transient);
}
} // namespace config
+62 -17
View File
@@ -40,6 +40,7 @@ Option<bool> ForceFreePlay("ForceFreePlay", true);
Option<bool, false> FetchBoxart("FetchBoxart", true);
Option<bool, false> BoxartDisplayMode("BoxartDisplayMode", true);
Option<int, false> UIScaling("UIScaling", 100);
Option<int, false> UITheme("UITheme", 0);
// Sound
@@ -71,11 +72,13 @@ Option<bool> ShowFPS("rend.ShowFPS");
Option<bool> RenderToTextureBuffer("rend.RenderToTextureBuffer");
Option<bool> TranslucentPolygonDepthMask("rend.TranslucentPolygonDepthMask");
Option<bool> ModifierVolumes("rend.ModifierVolumes", true);
Option<int> TextureUpscale("rend.TextureUpscale", 1);
Option<int> TextureUpscale("rend.TextureUpscale2", 1);
Option<int> MaxFilteredTextureSize("rend.MaxFilteredTextureSize", 256);
Option<float> ExtraDepthScale("rend.ExtraDepthScale", 1.f);
Option<bool> CustomTextures("rend.CustomTextures");
Option<bool> PreloadCustomTextures("rend.PreloadCustomTextures");
Option<bool> DumpTextures("rend.DumpTextures");
Option<bool> DumpReplacedTextures("rend.DumpReplacedTextures");
Option<int> ScreenStretching("rend.ScreenStretching", 100);
Option<bool> Fog("rend.Fog", true);
Option<bool> FloatVMUs("rend.FloatVMUs");
@@ -98,6 +101,8 @@ Option<int> SkipFrame("ta.skip");
Option<int> MaxThreads("pvr.MaxThreads", 3);
Option<int> AutoSkipFrame("pvr.AutoSkipFrame", 0);
Option<int> RenderResolution("rend.Resolution", 480);
Option<bool> IntegerScale("rend.IntegerScale", false);
Option<bool> LinearInterpolation("rend.LinearInterpolation", true);
Option<bool> VSync("rend.vsync", true);
Option<int64_t> PixelBufferSize("rend.PixelBufferSize", 512_MB);
Option<int> AnisotropicFiltering("rend.AnisotropicFiltering", 1);
@@ -105,9 +110,14 @@ Option<int> TextureFiltering("rend.TextureFiltering", 0); // Default
Option<bool> ThreadedRendering("rend.ThreadedRendering", true);
Option<bool> DupeFrames("rend.DupeFrames", false);
Option<int> PerPixelLayers("rend.PerPixelLayers", 32);
#ifdef TARGET_UWP
Option<bool> NativeDepthInterpolation("rend.NativeDepthInterpolation", true);
#else
Option<bool> NativeDepthInterpolation("rend.NativeDepthInterpolation", false);
#endif
Option<bool> EmulateFramebuffer("rend.EmulateFramebuffer", false);
Option<bool> FixUpscaleBleedingEdge("rend.FixUpscaleBleedingEdge", true);
Option<bool> CustomGpuDriver("rend.CustomGpuDriver", false);
#ifdef VIDEO_ROUTING
Option<bool, false> VideoRouting("rend.VideoRouting", false);
Option<bool, false> VideoRoutingScale("rend.VideoRoutingScale", false);
@@ -128,8 +138,22 @@ Option<bool> RamMod32MB("Dreamcast.RamMod32MB", false);
Option<bool> OpenGlChecks("OpenGlChecks", false, "validate");
Option<std::vector<std::string>, false> ContentPath("Dreamcast.ContentPath");
Option<std::vector<std::string>, false> BiosPath("Dreamcast.BiosPath");
Option<std::string, false> VMUPath("Dreamcast.VMUPath");
Option<std::vector<std::string>, false> SavestatePath("Dreamcast.SavestatePath");
Option<std::string, false> SavePath("Dreamcast.SavePath");
Option<std::vector<std::string>, false> TexturePath("Dreamcast.TexturePath");
Option<std::string, false> TextureDumpPath("Dreamcast.TextureDumpPath");
Option<std::string, false> BoxartPath("Dreamcast.BoxartPath");
Option<std::vector<std::string>, false> MappingsPath("Dreamcast.MappingsPath");
Option<std::vector<std::string>, false> CheatPath("Dreamcast.CheatPath");
Option<bool, false> HideLegacyNaomiRoms("Dreamcast.HideLegacyNaomiRoms", true);
Option<bool, false> UploadCrashLogs("UploadCrashLogs", true);
Option<bool, false> DiscordPresence("DiscordPresence", true);
#if defined(__ANDROID__) && !defined(LIBRETRO)
Option<bool, false> UseSafFilePicker("UseSafFilePicker", true);
#endif
OptionString LogServer("LogServer", "", "log");
// Profiler
Option<bool> ProfilerEnabled("Profiler.Enabled");
@@ -141,7 +165,7 @@ Option<float> ProfilerFrameWarningTime("Profiler.FrameWarningTime", 1.0f / 55.0f
Option<bool> NetworkEnable("Enable", false, "network");
Option<bool> ActAsServer("ActAsServer", false, "network");
OptionString DNS("DNS", "46.101.91.123", "network");
OptionString DNS("DNS", "dns.flyca.st", "network");
OptionString NetworkServer("server", "", "network");
Option<int> LocalPort("LocalPort", NaomiNetwork::SERVER_PORT, "network");
Option<bool> EmulateBBA("EmulateBBA", false, "network");
@@ -156,10 +180,8 @@ Option<int> GGPOChatTimeout("GGPOChatTimeout", 10, "network");
Option<bool> NetworkOutput("NetworkOutput", false, "network");
Option<int> MultiboardSlaves("MultiboardSlaves", 1, "network");
Option<bool> BattleCableEnable("BattleCable", false, "network");
#ifdef SUPPORT_DISPMANX
Option<bool> DispmanxMaintainAspect("maintain_aspect", true, "dispmanx");
#endif
Option<bool> UseDCNet("DCNet", false, "network");
OptionString ISPUsername("ISPUsername", "flycast1", "network");
#ifdef USE_OMX
Option<int> OmxAudioLatency("audio_latency", 100, "omx");
@@ -170,6 +192,7 @@ Option<bool> OmxAudioHdmi("audio_hdmi", true, "omx");
Option<int> MouseSensitivity("MouseSensitivity", 100, "input");
Option<int> VirtualGamepadVibration("VirtualGamepadVibration", 20, "input");
Option<int> VirtualGamepadTransparency("VirtualGamepadTransparency", 37, "input");
std::array<Option<MapleDeviceType>, 4> MapleMainDevices {
Option<MapleDeviceType>("device1", MDT_SegaController, "input"),
@@ -177,26 +200,48 @@ std::array<Option<MapleDeviceType>, 4> MapleMainDevices {
Option<MapleDeviceType>("device3", MDT_None, "input"),
Option<MapleDeviceType>("device4", MDT_None, "input"),
};
std::array<std::array<Option<MapleDeviceType>, 2>, 4> MapleExpansionDevices {
Option<MapleDeviceType>("device1.1", MDT_SegaVMU, "input"),
Option<MapleDeviceType>("device1.2", MDT_SegaVMU, "input"),
std::array<std::array<Option<MapleDeviceType>, 2>, 4> MapleExpansionDevices {{
{{Option<MapleDeviceType>("device1.1", MDT_SegaVMU, "input"),
Option<MapleDeviceType>("device1.2", MDT_SegaVMU, "input")}},
Option<MapleDeviceType>("device2.1", MDT_None, "input"),
Option<MapleDeviceType>("device2.2", MDT_None, "input"),
{{Option<MapleDeviceType>("device2.1", MDT_None, "input"),
Option<MapleDeviceType>("device2.2", MDT_None, "input")}},
Option<MapleDeviceType>("device3.1", MDT_None, "input"),
Option<MapleDeviceType>("device3.2", MDT_None, "input"),
{{Option<MapleDeviceType>("device3.1", MDT_None, "input"),
Option<MapleDeviceType>("device3.2", MDT_None, "input")}},
Option<MapleDeviceType>("device4.1", MDT_None, "input"),
Option<MapleDeviceType>("device4.2", MDT_None, "input"),
};
Option<bool> PerGameVmu("PerGameVmu", false, "config");
{{Option<MapleDeviceType>("device4.1", MDT_None, "input"),
Option<MapleDeviceType>("device4.2", MDT_None, "input")}},
}};
std::array<std::array<Option<int>, 2>, 4> NetworkExpansionDevices{{
{{Option<int>("device1.1.net", 0, "input"),
Option<int>("device1.2.net", 0, "input")}},
{{Option<int>("device2.1.net", 0, "input"),
Option<int>("device2.2.net", 0, "input")}},
{{Option<int>("device3.1.net", 0, "input"),
Option<int>("device3.2.net", 0, "input")}},
{{Option<int>("device4.1.net", 0, "input"),
Option<int>("device4.2.net", 0, "input")}},
}};
Option<bool> PerGameVmu("PerGameVmu", true, "config");
#ifdef _WIN32
Option<bool, false> UseRawInput("RawInput", false, "input");
#endif
Option<bool> UsePhysicalVmuMemory("UsePhysicalVmuMemory", false);
#ifdef USE_LUA
Option<std::string, false> LuaFileName("LuaFileName", "flycast.lua");
#endif
// RetroAchievements
Option<bool> EnableAchievements("Enabled", false, "achievements");
Option<bool> AchievementsHardcoreMode("HardcoreMode", false, "achievements");
OptionString AchievementsUserName("UserName", "", "achievements");
OptionString AchievementsToken("Token", "", "achievements");
} // namespace config
+50 -28
View File
@@ -56,7 +56,7 @@ public:
{
if (gameId.empty())
return;
if (!cfgHasSection(gameId))
if (!hasSection(gameId))
return;
perGameConfig = true;
}
@@ -65,10 +65,10 @@ public:
}
void save() {
cfgSetAutoSave(false);
setAutoSave(false);
for (const auto& o : options)
o->save();
cfgSetAutoSave(true);
setAutoSave(true);
}
void setGameId(const std::string& gameId) {
@@ -82,7 +82,7 @@ public:
this->perGameConfig = perGameConfig;
if (!perGameConfig) {
if (!gameId.empty())
cfgDeleteSection(gameId);
deleteSection(gameId);
reset();
}
}
@@ -122,7 +122,7 @@ public:
else
{
set(doLoad(section, name));
if (cfgIsVirtual(section, name))
if (isTransient(section, name))
override(value);
}
}
@@ -141,7 +141,7 @@ public:
if (value == doLoad(section, name))
{
// delete existing per-game option if any
cfgDeleteEntry(settings.gameId, section + "." + name);
deleteEntry(settings.gameId, section + "." + name);
return;
}
}
@@ -173,14 +173,14 @@ protected:
std::enable_if_t<std::is_same_v<U, bool>, T>
doLoad(const std::string& section, const std::string& name) const
{
return cfgLoadBool(section, name, value);
return loadBool(section, name, value);
}
template <typename U = T>
std::enable_if_t<std::is_same<U, int64_t>::value, T>
doLoad(const std::string& section, const std::string& name) const
{
return cfgLoadInt64(section, name, value);
return loadInt64(section, name, value);
}
template <typename U = T>
@@ -188,32 +188,28 @@ protected:
&& !std::is_same_v<U, bool> && !std::is_same_v<U, int64_t>, T>
doLoad(const std::string& section, const std::string& name) const
{
return (T)cfgLoadInt(section, name, (int)value);
return (T)loadInt(section, name, (int)value);
}
template <typename U = T>
std::enable_if_t<std::is_same_v<U, std::string>, T>
doLoad(const std::string& section, const std::string& name) const
{
return cfgLoadStr(section, name, value);
return loadStr(section, name, value);
}
template <typename U = T>
std::enable_if_t<std::is_same_v<float, U>, T>
doLoad(const std::string& section, const std::string& name) const
{
std::string strValue = cfgLoadStr(section, name, "");
if (strValue.empty())
return value;
else
return (float)atof(strValue.c_str());
return loadFloat(section, name, value);
}
template <typename U = T>
std::enable_if_t<std::is_same_v<std::vector<std::string>, U>, T>
doLoad(const std::string& section, const std::string& name) const
{
std::string paths = cfgLoadStr(section, name, "");
std::string paths = loadStr(section, name);
if (paths.empty())
return value;
std::string::size_type start = 0;
@@ -272,14 +268,14 @@ protected:
std::enable_if_t<std::is_same_v<U, bool>>
doSave(const std::string& section, const std::string& name) const
{
cfgSaveBool(section, name, value);
saveBool(section, name, value);
}
template <typename U = T>
std::enable_if_t<std::is_same<U, int64_t>::value>
doSave(const std::string& section, const std::string& name) const
{
cfgSaveInt64(section, name, value);
saveInt64(section, name, value);
}
template <typename U = T>
@@ -287,23 +283,21 @@ protected:
&& !std::is_same_v<U, bool> && !std::is_same_v<U, int64_t>>
doSave(const std::string& section, const std::string& name) const
{
cfgSaveInt(section, name, (int)value);
saveInt(section, name, (int)value);
}
template <typename U = T>
std::enable_if_t<std::is_same_v<U, std::string>>
doSave(const std::string& section, const std::string& name) const
{
cfgSaveStr(section, name, value);
saveStr(section, name, value);
}
template <typename U = T>
std::enable_if_t<std::is_same_v<float, U>>
doSave(const std::string& section, const std::string& name) const
{
char buf[64];
snprintf(buf, sizeof(buf), "%f", value);
cfgSaveStr(section, name, buf);
saveFloat(section, name, value);
}
template <typename U = T>
@@ -338,7 +332,7 @@ protected:
else
s += v;
}
cfgSaveStr(section, name, s);
saveStr(section, name, s);
}
std::string section;
@@ -373,6 +367,7 @@ extern Option<bool> ForceFreePlay;
extern Option<bool, false> FetchBoxart;
extern Option<bool, false> BoxartDisplayMode;
extern Option<int, false> UIScaling;
extern Option<int, false> UITheme; // 0 -> Dark, 1 -> Light, 2 -> Dreamcast, 3 -> High Contrast, 4 -> Nintendo, 5 -> Aqua Chill
// Sound
@@ -451,7 +446,9 @@ extern Option<int> PerPixelLayers;
#endif
extern Option<float> ExtraDepthScale;
extern Option<bool> CustomTextures;
extern Option<bool> PreloadCustomTextures;
extern Option<bool> DumpTextures;
extern Option<bool> DumpReplacedTextures;
extern Option<int> ScreenStretching; // in percent. 150 means stretch from 4/3 to 6/3
extern Option<bool> Fog;
extern Option<bool> FloatVMUs;
@@ -465,6 +462,8 @@ extern Option<int> SkipFrame;
extern Option<int> MaxThreads;
extern Option<int> AutoSkipFrame; // 0: none, 1: some, 2: more
extern Option<int> RenderResolution;
extern Option<bool> IntegerScale;
extern Option<bool> LinearInterpolation;
extern Option<bool> VSync;
extern Option<int64_t> PixelBufferSize;
extern Option<int> AnisotropicFiltering;
@@ -474,6 +473,7 @@ extern Option<bool> DupeFrames;
extern Option<bool> NativeDepthInterpolation;
extern Option<bool> EmulateFramebuffer;
extern Option<bool> FixUpscaleBleedingEdge;
extern Option<bool> CustomGpuDriver;
#ifdef VIDEO_ROUTING
extern Option<bool, false> VideoRouting;
extern Option<bool, false> VideoRoutingScale;
@@ -494,8 +494,22 @@ extern Option<bool> RamMod32MB;
extern Option<bool> OpenGlChecks;
extern Option<std::vector<std::string>, false> ContentPath;
extern Option<std::vector<std::string>, false> BiosPath;
extern Option<std::string, false> VMUPath;
extern Option<std::vector<std::string>, false> SavestatePath;
extern Option<std::string, false> SavePath;
extern Option<std::vector<std::string>, false> TexturePath;
extern Option<std::string, false> TextureDumpPath;
extern Option<std::string, false> BoxartPath;
extern Option<std::vector<std::string>, false> MappingsPath;
extern Option<std::vector<std::string>, false> CheatPath;
extern Option<bool, false> HideLegacyNaomiRoms;
extern Option<bool, false> UploadCrashLogs;
extern Option<bool, false> DiscordPresence;
#if defined(__ANDROID__) && !defined(LIBRETRO)
extern Option<bool, false> UseSafFilePicker;
#endif
extern OptionString LogServer;
// Profiling
extern Option<bool> ProfilerEnabled;
@@ -522,10 +536,8 @@ extern Option<int> GGPOChatTimeout;
extern Option<bool> NetworkOutput;
extern Option<int> MultiboardSlaves;
extern Option<bool> BattleCableEnable;
#ifdef SUPPORT_DISPMANX
extern Option<bool> DispmanxMaintainAspect;
#endif
extern Option<bool> UseDCNet;
extern OptionString ISPUsername;
#ifdef USE_OMX
extern Option<int> OmxAudioLatency;
@@ -536,17 +548,27 @@ extern Option<bool> OmxAudioHdmi;
extern Option<int> MouseSensitivity;
extern Option<int> VirtualGamepadVibration;
extern Option<int> VirtualGamepadTransparency;
extern std::array<Option<MapleDeviceType>, 4> MapleMainDevices;
extern std::array<std::array<Option<MapleDeviceType>, 2>, 4> MapleExpansionDevices;
extern std::array<std::array<Option<int>, 2>, 4> NetworkExpansionDevices;
extern Option<bool> PerGameVmu;
#ifdef _WIN32
extern Option<bool, false> UseRawInput;
#else
constexpr bool UseRawInput = false;
#endif
extern Option<bool> UsePhysicalVmuMemory;
#ifdef USE_LUA
extern Option<std::string, false> LuaFileName;
#endif
// RetroAchievements
extern Option<bool> EnableAchievements;
extern Option<bool> AchievementsHardcoreMode;
extern OptionString AchievementsUserName;
extern OptionString AchievementsToken;
} // namespace config
+247 -83
View File
@@ -28,6 +28,8 @@
#include "cfg/option.h"
#include "emulator.h"
#include "oslib/storage.h"
#include "oslib/i18n.h"
using namespace i18n;
const WidescreenCheat CheatManager::widescreen_cheats[] =
{
@@ -83,7 +85,7 @@ const WidescreenCheat CheatManager::widescreen_cheats[] =
{ "T30006M", nullptr, { 0x4CF42C, 0x4CF45C, 0x3E1A36, 0x3E1A34, 0x3E1A3C, 0x3E1A54, 0x3E1A5C },
{ 0x43F00000, 0x3F400000, 0x08010000, 0, 0, 0, 0 } },
{ "MK-5103750", nullptr, { 0x1FE270 }, { 0x43700000 } }, // Daytona USA (PAL)
{ "MK-51037", nullptr, { 0x1FC6D0 }, { 0x43700000 } }, // Daytona USA (USA)
// breaks online connection { "MK-51037", nullptr, { 0x1FC6D0 }, { 0x43700000 } }, // Daytona USA (USA)
{ "T9501N-50", nullptr, { 0x9821D4 }, { 0x3F400000 } }, // Deadly Skies (PAL)
{ "T8116D 50", nullptr, { 0x2E5530 }, { 0x43700000 } }, // Dead or Alive 2 (PAL)
{ "T3601N", nullptr, { 0x2F0670 }, { 0x43700000 } }, // Dead or Alive 2 (USA)
@@ -111,7 +113,7 @@ const WidescreenCheat CheatManager::widescreen_cheats[] =
{ "MK-5115450", nullptr, { 0x3D3B10 }, { 0x43700000 } }, // Fighting Vipers 2 (PAL)
{ "HDR-0133", nullptr, { 0x3D3AF0 }, { 0x43700000 } }, // Fighting Vipers 2 (JP)
{ "T18805M", nullptr, { 0x1A39C0 }, { 0x3F400000 } }, // Fire Pro Wrestling D (JP)
{ "MK-51114", nullptr, { 0x132DD8, 0xA26CA8, 0xA26738, 0xA275B8, 0xA26AD8, 0xA26908 },
{ "MK-51114", " E ", { 0x132DD8, 0xA26CA8, 0xA26738, 0xA275B8, 0xA26AD8, 0xA26908 },
{ 0x3F400000, 0x3F400000, 0x3F400000, 0x3F400000, 0x3F400000, 0x3F400000 } }, // Floigan Bros. Ep. 1 (PAL)
{ "T34201M", nullptr, { 0x586290, 0x586260 }, { 0x3F400000, 0x43F00000 } }, // Frame Gride (JP)
{ "T-8113D-50", nullptr, { 0x55A354 }, { 0x3FAAAAAB } }, // Fur Fighters (PAL)
@@ -165,10 +167,11 @@ const WidescreenCheat CheatManager::widescreen_cheats[] =
{ 0x43F00000, 0x3F400000, 0x3F800000 } }, // Napple Tale: Arsia in Daydream (JP)
//crash { "MK-51178", nullptr, { 0x23AF00, 0x23B160, 0x144D40, 0x2105B4, 0x705B40 },
// { 0xBFAAAAAB, 0xBFAAAAAB, 0xBFAAAAAB, 0xBFAAAAAB, 0x44558000 } }, // NBA 2K2
{ "T9504M", nullptr, { 0xCDE848, 0xCDE844 }, { 0x3F400000, 0x3FA00000 } }, // Nightmare Creatures II (USA)
{ "T-9502D-50", nullptr, { 0xBDE9B0, 0xBDE9C4 }, { 0x3F400000, 0x3FA00000 } }, // Nightmare Creatures II (PAL)
// { "T9504M", nullptr, { 0xCDE848, 0xCDE844 }, { 0x3F400000, 0x3FA00000 } }, // Nightmare Creatures II (USA)
// { "T-9502D-50", nullptr, { 0xBDE9B0, 0xBDE9C4 }, { 0x3F400000, 0x3FA00000 } }, // Nightmare Creatures II (PAL)
{ "MK-5110250", nullptr, { 0x87B5A4 }, { 0x43700000 } }, // Outtrigger (PAL)
{ "HDR-0118", nullptr, { 0x83E284 }, { 0x43700000 } }, // Outtrigger (JP)
{ "MK-51102", nullptr, { 0x83E284 }, { 0x43700000 } }, // Outtrigger (US)
{ "T15103D 50", nullptr, { 0x1EEE78 }, { 0x3F400000 } }, // PenPen (PAL)
{ "T17001M", nullptr, { 0x1C3828 }, { 0x3F400000 } }, // PenPen TriIcelon (JP)
{ "MK-5110050", nullptr, { 0x548E04, 0x0923C0 }, { 0x43E80000, 0x3F966666 } }, // Phantasy Star Online (PAL) TODO
@@ -225,6 +228,7 @@ const WidescreenCheat CheatManager::widescreen_cheats[] =
{ "T8104D 58", nullptr, { 0x2C03F8 }, { 0x44558000 } }, // Shadow Man (PAL)
{ "T-8106N", nullptr, { 0x2C03F4 }, { 0x3F400000 } }, // Shadow Man (USA)
{ "MK-51048", nullptr, { 0x4AA4DC, 0x2B4E30 }, { 0x3F400000, 0x3F400000 } }, // Seaman (USA)
{ "MK-51053", nullptr, { 0x5630CC }, { 0x3F400000 } }, // Sega GT (USA)
{ "MK-5105350", nullptr, { 0x5D613C }, { 0x3F400000 } }, // Sega GT (PAL)
{ "MK-51096", nullptr, { 0x495050 }, { 0x43700000 } }, // Sega Marine Fishing (USA)
// { "MK-51019", nullptr, { 0xB83A48 }, { 0x3F400000 } }, // Sega Rally 2 (USA) not working?
@@ -317,6 +321,7 @@ const WidescreenCheat CheatManager::naomi_widescreen_cheats[] =
{ "KNIGHTS OF VALOUR THE 7 SPIRITS", nullptr, { 0x475B70, 0x475B40 }, { 0x3F400000, 0x43F00000 } },
{ "Dolphin Blue", nullptr, { 0x3F2E2C, 0x3F2190, 0x3F2E6C, 0x3F215C },
{ 0x43B90000, 0x3FAA9FBE, 0x43B90000, 0x43F00000 } },
{ "FASTER THAN SPEED", nullptr, { 0x3488E0 }, { 0x3F400000 } }, // ftspeed
{ "METAL SLUG 6", nullptr, { 0xE93478, 0xE9347C }, { 0x3F400000, 0x3F8872B0 } },
{ "TOY FIGHTER", nullptr, { 0x133E58 }, { 0x43700000 } },
{ "LUPIN THE THIRD -THE SHOOTING-", nullptr, { 0x045490 }, { 0x3F400000 } },
@@ -375,24 +380,35 @@ void CheatManager::setActive(bool active)
void CheatManager::loadCheatFile(const std::string& filename)
{
#ifndef LIBRETRO
try {
hostfs::FileInfo fileInfo = hostfs::storage().getFileInfo(filename);
if (fileInfo.size >= 1_MB) {
WARN_LOG(COMMON, "Cheat file '%s' is too big", filename.c_str());
return;
}
} catch (const hostfs::StorageException& e) {
WARN_LOG(COMMON, "Cannot find cheat file '%s': %s", filename.c_str(), e.what());
return;
}
FILE* cheatfile = hostfs::storage().openFile(filename, "r");
if (cheatfile == nullptr)
{
WARN_LOG(COMMON, "Cannot open cheat file '%s'", filename.c_str());
return;
}
emucfg::ConfigFile cfg;
cfg.parse(cheatfile);
config::IniFile cfg;
cfg.load(cheatfile);
fclose(cheatfile);
int count = cfg.get_int("", "cheats", 0);
int count = cfg.getInt("", "cheats", 0);
cheats.clear();
for (int i = 0; count == 0 || i < count; i++)
{
std::string prefix = "cheat" + std::to_string(i) + "_";
Cheat cheat{};
cheat.description = cfg.get("", prefix + "desc", "Cheat " + std::to_string(i + 1));
cheat.address = cfg.get_int("", prefix + "address", -1);
cheat.description = cfg.getString("", prefix + "desc", "Cheat " + std::to_string(i + 1));
cheat.address = cfg.getInt("", prefix + "address", -1);
if (count == 0 && cheat.address == (u32)-1)
break;
if (cheat.address >= RAM_SIZE)
@@ -400,26 +416,27 @@ void CheatManager::loadCheatFile(const std::string& filename)
WARN_LOG(COMMON, "Invalid address %x", cheat.address);
continue;
}
cheat.type = (Cheat::Type)cfg.get_int("", prefix + "cheat_type", (int)Cheat::Type::disabled);
cheat.size = 1 << cfg.get_int("", prefix + "memory_search_size", 0);
cheat.value = cfg.get_int("", prefix + "value", cheat.value);
cheat.repeatCount = cfg.get_int("", prefix + "repeat_count", cheat.repeatCount);
cheat.repeatValueIncrement = cfg.get_int("", prefix + "repeat_add_to_value", cheat.repeatValueIncrement);
cheat.repeatAddressIncrement = cfg.get_int("", prefix + "repeat_add_to_address", cheat.repeatAddressIncrement);
cheat.enabled = cfg.get_bool("", prefix + "enable", false);
cheat.destAddress = cfg.get_int("", prefix + "dest_address", 0);
cheat.type = (Cheat::Type)cfg.getInt("", prefix + "cheat_type", (int)Cheat::Type::disabled);
cheat.size = 1 << cfg.getInt("", prefix + "memory_search_size", 0);
cheat.value = cfg.getInt("", prefix + "value", cheat.value);
cheat.repeatCount = cfg.getInt("", prefix + "repeat_count", cheat.repeatCount);
cheat.repeatValueIncrement = cfg.getInt("", prefix + "repeat_add_to_value", cheat.repeatValueIncrement);
cheat.repeatAddressIncrement = cfg.getInt("", prefix + "repeat_add_to_address", cheat.repeatAddressIncrement);
cheat.enabled = cfg.getBool("", prefix + "enable", false);
cheat.destAddress = cfg.getInt("", prefix + "dest_address", 0);
if (cheat.destAddress >= RAM_SIZE)
{
WARN_LOG(COMMON, "Invalid address %x", cheat.destAddress);
continue;
}
cheat.valueMask = cfg.get_int("", prefix + "address_bit_position", 0);
cheat.valueMask = cfg.getInt("", prefix + "address_bit_position", 0);
if (cheat.type != Cheat::Type::disabled)
cheats.push_back(cheat);
}
setActive(!cheats.empty());
INFO_LOG(COMMON, "%d cheats loaded", (int)cheats.size());
cfgSaveStr("cheats", gameId, filename);
if (!cheats.empty())
config::saveStr("cheats", gameId, filename);
#endif
}
@@ -431,10 +448,42 @@ void CheatManager::reset(const std::string& gameId)
cheats.clear();
setActive(false);
this->gameId = gameId;
#ifndef LIBRETRO
std::string cheatFile = cfgLoadStr("cheats", gameId, "");
if (!cheatFile.empty())
loadCheatFile(cheatFile);
if (!settings.raHardcoreMode)
{
std::string cheatFile = config::loadStr("cheats", gameId);
if (!cheatFile.empty())
loadCheatFile(cheatFile);
else
{
// Try to auto-locate a cheat file in user-defined CheatPath
std::string romName = settings.content.fileName;
const char* exts[] = { ".cht", ".txt" };
for (const auto& base : config::CheatPath.get())
{
if (base.empty())
continue;
for (const char* ext : exts)
{
try
{
std::string candidate = hostfs::storage().getSubPath(base, romName + ext);
if (hostfs::storage().exists(candidate))
{
loadCheatFile(candidate);
config::saveStr("cheats", gameId, candidate);
goto found_cheats;
}
}
catch (const hostfs::StorageException&)
{
}
}
}
}
}
found_cheats:
#endif
size_t cheatCount = cheats.size();
if (gameId == "Fixed BOOT strapper") // Extreme Hunting 2
@@ -449,31 +498,6 @@ void CheatManager::reset(const std::string& gameId)
else if (gameId == "THE KING OF ROUTE66") {
cheats.emplace_back(Cheat::Type::setValue, "ignore drive error", true, 32, 0x00023ee0, 0x0009000B, true); // rts, nop
}
else if (gameId.substr(0, 8) == "MKG TKOB")
{
const auto& setMushikingCheats = [this](u32 addr) {
cheats.emplace_back(Cheat::Type::setValue, "ignore rfid1 error", true, 32, addr, 0, true); // rfid[0].error = 0
cheats.emplace_back(Cheat::Type::setValue, "ignore rfid2 error", true, 32, addr + 0x48, 0, true); // rfid[1].error = 0
cheats.emplace_back(Cheat::Type::setValue, "ignore rfid1 status", true, 32, addr + 8, 0, true); // rfid[0].data18 = 0
cheats.emplace_back(Cheat::Type::setValue, "ignore rfid2 status", true, 32, addr + 0x50, 0, true); // rfid[1].data18 = 0
};
if (gameId == "MKG TKOB 2 EXP VER1.001-") // mushi2eo
setMushikingCheats(0x6fe1bc);
else if (gameId == "MKG TKOB 2 JPN VER2.001-") // mushik2e
setMushikingCheats(0x6ffe54);
else if (gameId == "MKG TKOB 2K3 2ND VER1.003-")// mushike
setMushikingCheats(0x4ad7ec);
else if (gameId == "MKG TKOB 4 JPN VER2.000-") // mushik4e
setMushikingCheats(0xb0e538);
else if (gameId == "MKG TKOB 2K3 2ND VER1.002-")// mushikeo
setMushikingCheats(0x4ad56c);
else if (gameId == "MKG TKOB 2K3 2ND KOR VER1.000-") // mushikk
setMushikingCheats(0x4ac9b8);
else if (gameId == "MKG TKOB 2K3 2ND CHN VER1.000-") // mushikc
setMushikingCheats(0x4aa9b8);
else if (gameId == "MKG TKOB 2 KOR VER1.000-") // mushik2k
setMushikingCheats(0x706084);
}
else if (gameId == "T-8120N") { // Dave Mirra BMX (US)
cheats.emplace_back(Cheat::Type::setValue, "fix main loop time", true, 32, 0x0030b8cc, 0x42040000, true); // 33.0 ms
}
@@ -489,10 +513,86 @@ void CheatManager::reset(const std::string& gameId)
else if (gameId == "SAMURAI SPIRITS 6" || gameId == "T0002M") {
cheats.emplace_back(Cheat::Type::setValue, "fix depth", true, 16, 0x0003e602, 0x0009, true); // nop (shift by 8 bits instead of 10)
}
else if (gameId == "T-8107N") { // Fur Fighters (US)
// force logging on to use more cycles
cheats.emplace_back(Cheat::Type::setValue, "enable logging", true, 32, 0x00314248, 1, true);
}
else if (gameId == "T-8113D-50") { // Fur Fighters (EU)
// force logging on to use more cycles
cheats.emplace_back(Cheat::Type::setValue, "enable logging", true, 32, 0x00314228, 1, true);
}
// Dricas auth bypass
else if (gameId == "T6807M") // Aero Dancing i
{
// modem
cheats.emplace_back(Cheat::Type::runNextIfEq, "bypass auth ifeq", true, 32, 0x0004b7a0, 0x2fd62fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bypass dricas auth", true, 32, 0x0004b7a0, 0xe000000b, true); // rts, _mov #0, r0
// BBA
cheats.emplace_back(Cheat::Type::runNextIfEq, "bba bypass auth ifeq", true, 32, 0x0004af5c, 0x2fd62fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bba bypass dricas auth", true, 32, 0x0004af5c, 0xe000000b, true);
// IP check
cheats.emplace_back(Cheat::Type::runNextIfEq, "ip check ifeq", true, 32, 0x00020860, 0x4f222fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "ip check ok", true, 32, 0x00020860, 0xe000000b, true);
}
else if (gameId == "T6809M") // Aero Dancing i - Jikai Saku Made Matemasen
{
// modem
cheats.emplace_back(Cheat::Type::runNextIfEq, "bypass auth ifeq", true, 32, 0x0004b940, 0x2fd62fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bypass dricas auth", true, 32, 0x0004b940, 0xe000000b, true);
// BBA
cheats.emplace_back(Cheat::Type::runNextIfEq, "bba bypass auth ifeq", true, 32, 0x0004f848, 0x2fd62fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bba bypass dricas auth", true, 32, 0x0004f848, 0xe000000b, true);
// IP check
cheats.emplace_back(Cheat::Type::runNextIfEq, "ip check ifeq", true, 32, 0x00020980, 0x4f222fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "ip check ok", true, 32, 0x00020980, 0xe000000b, true);
}
else if (gameId == "T6805M") { // Aero Dancing F - Todoroki Tsubasa no Hatsu Hikou
cheats.emplace_back(Cheat::Type::runNextIfEq, "bypass auth ifeq", true, 32, 0x0003ed10, 0x2fd62fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bypass dricas auth", true, 32, 0x0003ed10, 0xe000000b, true);
}
else if (gameId == "HDR-0106") { // Daytona USA (JP)
cheats.emplace_back(Cheat::Type::runNextIfEq, "bypass auth ifeq", true, 32, 0x0003ad30, 0x2fd62fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bypass dricas auth", true, 32, 0x0003ad30, 0xe000000b, true);
}
else if (gameId == "HDR-0073") { // Sega Tetris
cheats.emplace_back(Cheat::Type::runNextIfEq, "bypass auth ifeq", true, 32, 0x000a56f8, 0x2fd62fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bypass dricas auth", true, 32, 0x000a56f8, 0xe000000b, true);
}
else if (gameId == "T44501M") { // Golf Shiyou Yo 2
cheats.emplace_back(Cheat::Type::runNextIfEq, "bypass auth ifeq", true, 32, 0x0013f150, 0x2fd62fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bypass dricas auth", true, 32, 0x0013f150, 0xe000000b, true);
}
else if (gameId == "HDR-0124") { // Hundred Swords
cheats.emplace_back(Cheat::Type::runNextIfEq, "bypass auth ifeq", true, 32, 0x006558ac, 0x1f414f22, true);
cheats.emplace_back(Cheat::Type::setValue, "bypass dricas auth", true, 32, 0x006558ac, 0xe000000b, true);
}
else if (gameId == "T43903M") { // Culdcept II
cheats.emplace_back(Cheat::Type::runNextIfEq, "bypass auth ifeq", true, 32, 0x00800524, 0x2fd62fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bypass dricas auth", true, 32, 0x00800524, 0xe000000b, true);
}
else if (gameId == "HDR-0118") { // Outtrigger (JP)
cheats.emplace_back(Cheat::Type::runNextIfEq, "bypass auth ifeq", true, 32, 0x00139f54, 0x2fd62fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bypass dricas auth", true, 32, 0x00139f54, 0xe000000b, true);
}
else if (gameId == "HDR-0113") // Power Smash
{
cheats.emplace_back(Cheat::Type::runNextIfEq, "no dupe SYN ifeq", true, 16, 0x14d258, 0xbbce, true); // bsr SendNormalSYN
cheats.emplace_back(Cheat::Type::setValue, "no dupe SYN set", true, 16, 0x14d258, 0x0009, true); // nop
cheats.emplace_back(Cheat::Type::runNextIfEq, "no dupe ACK ifeq", true, 16, 0x14af42, 0x430b, true); // jsr TCPInternalSendPacket
cheats.emplace_back(Cheat::Type::setValue, "no dupe ACK set", true, 16, 0x14af42, 0x0009, true); // nop
}
else if (gameId == "HDR-0091") // Pro Yakyuu Team de Asobou Net!
{
cheats.emplace_back(Cheat::Type::runNextIfEq, "no dupe SYN ifeq", true, 16, 0xe13e0c, 0xbbce, true); // bsr SendNormalSYN
cheats.emplace_back(Cheat::Type::setValue, "no dupe SYN set", true, 16, 0xe13e0c, 0x0009, true); // nop
cheats.emplace_back(Cheat::Type::runNextIfEq, "no dupe ACK ifeq", true, 16, 0xe11af6, 0x430b, true); // jsr TCPInternalSendPacket
cheats.emplace_back(Cheat::Type::setValue, "no dupe ACK set", true, 16, 0xe11af6, 0x0009, true); // nop
}
if (cheats.size() > cheatCount)
setActive(true);
}
if (config::WidescreenGameHacks)
if (config::WidescreenGameHacks && !settings.raHardcoreMode)
{
if (settings.platform.isConsole())
{
@@ -668,18 +768,54 @@ static std::vector<u32> parseCodes(const std::string& s)
}
}
else if (!curCode.empty())
throw FlycastException("Invalid cheat code");
throw FlycastException(Ts("Invalid cheat code"));
}
if (!curCode.empty())
{
if (curCode.length() != 8)
throw FlycastException("Invalid cheat code");
throw FlycastException(Ts("Invalid cheat code"));
codes.push_back(strtoul(curCode.c_str(), nullptr, 16));
}
return codes;
}
// Decrypt (some) Action Replay/Gameshark/Codebreaker/Xploder encrypted codes
// Master codes change the encryption method and thus are not supported (07xxxxxx)
// Taken from DCcrypt
constexpr u32 Seeds[16] = {
0xA53A8888,
0xA1427921, 0xAC9528B1, 0xC5892354, 0x49671B12,
0xACC56121, 0xACB5381E, 0x765436E1, 0x9F2C3E54,
0x1133E312, 0xAC5E7894, 0xE9F208B1, 0x4E87DCFE,
0x43174312, 0x1D7A6C99, 0x874224A2
};
static u32 decryptCode(u32 v)
{
constexpr u32 something = 6;
if ((v & 0xf0000000) == 0)
return v;
u32 seed = Seeds[v >> 28];
if (something & 4)
v = (((v << 1) & 0x0FFFFFFE) | ((v >> 27) & 1));
if (something & 2) {
v = (((v << 1) & 0x0FFFFFFE) | ((v >> 27) & 1));
v = (((v << 8) & 0x0FFFFF00) | ((v >> 20) & 0xFF));
}
if (something & 1)
seed >>= 4;
u32 ret = (seed & 0x0FFFFFFF) ^ v;
//if ((ret & 0x0FF00000) != 0x07100000)
// something = (ret & 0x0f) + 6;
return ret;
}
static u32 decryptArg(u32 v) {
return (((v + 0x543700D0) >> 29) | ((v + 0x543700D0) * 8)) ^ Seeds[0];
}
void CheatManager::addGameSharkCheat(const std::string& name, const std::string& s)
{
std::vector<u32> codes = parseCodes(s);
@@ -695,6 +831,22 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
Cheat cheat{};
cheat.description = name;
u32 code = (codes[i] & 0xff000000) >> 24;
if (code & 0xf0)
{
// encrypted code
codes[i] = decryptCode(codes[i]);
code = (codes[i] & 0xff000000) >> 24;
if (code == 4 && i + 2 < codes.size()) {
// following args are also encrypted
codes[i + 1] = decryptArg(codes[i + 1]);
codes[i + 2] = decryptArg(codes[i + 2]);
}
else if (code == 0xd && i + 2 < codes.size()) {
// following arg is also encrypted
codes[i + 1] = decryptArg(codes[i + 1]);
}
// TODO Which ops have encrypted args (3, 5, E, F)? Couldn't find any
}
switch (code)
{
case 0:
@@ -703,7 +855,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
{
// 8/16/32-bit write
if (i + 1 >= codes.size())
throw FlycastException("Missing value");
throw FlycastException(Ts("Missing value"));
cheat.type = Cheat::Type::setValue;
cheat.size = code == 0 ? 8 : code == 1 ? 16 : 32;
cheat.address = codes[i] & 0x00ffffff;
@@ -721,7 +873,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
// Group write
int count = codes[i] & 0xffff;
if (i + count + 1 >= codes.size())
throw FlycastException("Missing values");
throw FlycastException(Ts("Missing values"));
cheat.type = Cheat::Type::setValue;
cheat.size = 32;
cheat.address = codes[++i] & 0x00ffffff;
@@ -742,7 +894,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
{
// 8-bit inc/decrement
if (i + 1 >= codes.size())
throw FlycastException("Missing value");
throw FlycastException(Ts("Missing value"));
cheat.type = subcode == 1 ? Cheat::Type::increase : Cheat::Type::decrease;
cheat.size = 8;
cheat.value = codes[i] & 0xff;
@@ -755,7 +907,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
{
// 16-bit inc/decrement
if (i + 1 >= codes.size())
throw FlycastException("Missing value");
throw FlycastException(Ts("Missing value"));
cheat.type = subcode == 3 ? Cheat::Type::increase : Cheat::Type::decrease;
cheat.size = 16;
cheat.value = codes[i] & 0xffff;
@@ -768,7 +920,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
{
// 32-bit inc/decrement
if (i + 2 >= codes.size())
throw FlycastException("Missing address or value");
throw FlycastException(Ts("Missing address or value"));
cheat.type = subcode == 5 ? Cheat::Type::increase : Cheat::Type::decrease;
cheat.size = 32;
cheat.address = codes[++i] & 0x00ffffff;
@@ -777,7 +929,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
}
break;
default:
throw FlycastException("Unsupported cheat type");
throw FlycastException(Ts("Unsupported cheat type"));
}
}
break;
@@ -785,7 +937,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
{
// 32-bit repeat write
if (i + 2 >= codes.size())
throw FlycastException("Missing count or value");
throw FlycastException(Ts("Missing count or value"));
cheat.type = Cheat::Type::setValue;
cheat.size = 32;
cheat.address = codes[i] & 0x00ffffff;
@@ -799,7 +951,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
{
// copy bytes
if (i + 2 >= codes.size())
throw FlycastException("Missing count or destination address");
throw FlycastException(Ts("Missing count or destination address"));
cheat.type = Cheat::Type::copy;
cheat.size = 8;
cheat.address = codes[i] & 0x00ffffff;
@@ -808,14 +960,22 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
cheats.push_back(cheat);
}
break;
// TODO 7 change decryption type
// TODO 0xb delay applying codes
// TODO 0xc global enable test
case 7:
// change decryption type: 071000XX (example: 07100005)
throw FlycastException(Ts("Master codes aren't supported"));
// TODO 0xb delay applying codes: 0b0xxxxx
// Delay putting on codes for xxxxx cycles. Default 1000 (0x3e7)
// TODO 0xc global enable test: 0cxxxxxx vvvvvvvv
// If the value at address 8Cxxxxxx is equal to vvvvvvvv, execute ALL codes;
// otherwise no codes are executed. Useful for waiting until game has loaded.
case 0xd:
{
// enable next code if eq/neq/lt/gt
if (i + 1 >= codes.size())
throw FlycastException("Missing count or destination address");
throw FlycastException(Ts("Missing count or destination address"));
cheat.size = 16;
cheat.address = codes[i] & 0x00ffffff;
switch (codes[++i] >> 16)
@@ -833,7 +993,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
cheat.type = Cheat::Type::runNextIfGt;
break;
default:
throw FlycastException("Unsupported conditional code");
throw FlycastException(Ts("Unsupported conditional code"));
}
cheat.value = codes[i] & 0xffff;
cheats.push_back(cheat);
@@ -843,7 +1003,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
{
// multiline enable codes if eq/neq/lt/gt
if (i + 1 >= codes.size())
throw FlycastException("Missing test address");
throw FlycastException(Ts("Missing test address"));
cheat.size = 16;
cheat.value = codes[i] & 0xffff;
conditionLimit = i + 1 + ((codes[i] >> 16) & 0xff);
@@ -862,22 +1022,26 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
cheat.type = Cheat::Type::runNextIfGt;
break;
default:
throw FlycastException("Unsupported conditional code");
throw FlycastException(Ts("Unsupported conditional code"));
}
cheat.address = codes[i] & 0x00ffffff;
conditionCheat = cheat;
}
break;
// TODO 0xF: 0F-XXXXXX 0000YYYY
// 16-Bit Write Once Immediately. (Activator code)
default:
throw FlycastException("Unsupported cheat type");
throw FlycastException(Ts("Unsupported cheat type"));
}
}
#ifndef LIBRETRO
std::string path = cfgLoadStr("cheats", gameId, "");
std::string path = config::loadStr("cheats", gameId);
if (path == "")
{
path = get_game_save_prefix() + ".cht";
cfgSaveStr("cheats", gameId, path);
config::saveStr("cheats", gameId, path);
}
saveCheatFile(path);
#endif
@@ -891,7 +1055,7 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
void CheatManager::saveCheatFile(const std::string& filename)
{
#ifndef LIBRETRO
emucfg::ConfigFile cfg;
config::IniFile cfg;
int i = 0;
for (const Cheat& cheat : cheats)
@@ -899,15 +1063,15 @@ void CheatManager::saveCheatFile(const std::string& filename)
if (cheat.builtIn)
continue;
std::string prefix = "cheat" + std::to_string(i) + "_";
cfg.set_int("", prefix + "address", cheat.address);
cfg.set_int("", prefix + "address_bit_position", cheat.valueMask);
cfg.set_bool("", prefix + "big_endian", false);
cfg.set_int("", prefix + "cheat_type", (int)cheat.type);
cfg.set("", prefix + "address", cheat.address);
cfg.set("", prefix + "address_bit_position", cheat.valueMask);
cfg.set("", prefix + "big_endian", false);
cfg.set("", prefix + "cheat_type", (int)cheat.type);
cfg.set("", prefix + "code", "");
cfg.set("", prefix + "desc", cheat.description);
cfg.set_int("", prefix + "dest_address", cheat.destAddress);
cfg.set_bool("", prefix + "enable", false); // force all cheats disabled at start
cfg.set_int("", prefix + "handler", 1);
cfg.set("", prefix + "dest_address", cheat.destAddress);
cfg.set("", prefix + "enable", false); // force all cheats disabled at start
cfg.set("", prefix + "handler", 1);
int memSize;
switch (cheat.size) {
case 1:
@@ -930,17 +1094,17 @@ void CheatManager::saveCheatFile(const std::string& filename)
memSize = 5;
break;
}
cfg.set_int("", prefix + "memory_search_size", memSize);
cfg.set_int("", prefix + "value", cheat.value);
cfg.set_int("", prefix + "repeat_count", cheat.repeatCount);
cfg.set_int("", prefix + "repeat_add_to_value", cheat.repeatValueIncrement);
cfg.set_int("", prefix + "repeat_add_to_address", cheat.repeatAddressIncrement);
cfg.set("", prefix + "memory_search_size", memSize);
cfg.set("", prefix + "value", cheat.value);
cfg.set("", prefix + "repeat_count", cheat.repeatCount);
cfg.set("", prefix + "repeat_add_to_value", cheat.repeatValueIncrement);
cfg.set("", prefix + "repeat_add_to_address", cheat.repeatAddressIncrement);
i++;
}
cfg.set_int("", "cheats", i);
cfg.set("", "cheats", i);
FILE *fp = hostfs::storage().openFile(filename.c_str(), "w");
if (fp == nullptr)
throw FlycastException("Can't save cheat file");
throw FlycastException(Ts("Can't save cheat file"));
cfg.save(fp);
fclose(fp);
#endif
+8 -8
View File
@@ -21,7 +21,7 @@
#include "emulator.h"
#include "hw/sh4/sh4_if.h"
#include "hw/sh4/sh4_mem.h"
#include "hw/sh4/sh4_interpreter.h"
#include "hw/sh4/dyna/shil.h"
#include "cfg/option.h"
#include <array>
#include <signal.h>
@@ -122,9 +122,9 @@ public:
for (u32 i = 0; i < Sh4RegList.size(); i++)
{
if (Sh4RegList[i] == reg_sr_status)
allregs[i] = sh4_sr_GetFull();
allregs[i] = Sh4cntx.sr.getFull();
else if (Sh4RegList[i] != NoReg)
allregs[i] = *GetRegPtr(Sh4RegList[i]);
allregs[i] = *GetRegPtr(Sh4cntx, Sh4RegList[i]);
}
*regs = &allregs[0];
return allregs.size();
@@ -134,7 +134,7 @@ public:
{
for (u32 i = 0; i < Sh4RegList.size(); i++)
if (Sh4RegList[i] != NoReg)
*GetRegPtr(Sh4RegList[i]) = regs[i];
*GetRegPtr(Sh4cntx, Sh4RegList[i]) = regs[i];
}
u32 readReg(u32 regNum)
@@ -143,9 +143,9 @@ public:
return 0;
Sh4RegType reg = Sh4RegList[regNum];
if (reg == reg_sr_status)
return sh4_sr_GetFull();
return Sh4cntx.sr.getFull();
if (reg != NoReg)
return *GetRegPtr(reg);
return *GetRegPtr(Sh4cntx, reg);
return 0;
}
void writeReg(u32 regNum, u32 value)
@@ -154,9 +154,9 @@ public:
return;
Sh4RegType reg = Sh4RegList[regNum];
if (reg == reg_sr_status)
sh4_sr_SetFull(value);
Sh4cntx.sr.setFull(value);
else if (reg != NoReg)
*GetRegPtr(reg) = value;
*GetRegPtr(Sh4cntx, reg) = value;
}
const u8 *readMem(u32 addr, u32 len)
+405 -390
View File
File diff suppressed because it is too large. Load diff
+1
Submodule core/deps/asio added at d3402006e8.
+26 -14
View File
@@ -38,7 +38,7 @@ unsigned long track_mode;
/////////////////////////////////////////////////////////////////////////////
void CDI_read_track (FILE *fsource, image_s *image, track_s *track)
bool CDI_read_track (FILE *fsource, image_s *image, track_s *track)
{
unsigned char TRACK_START_MARK[10] = { 0, 0, 0x01, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -49,10 +49,16 @@ void CDI_read_track (FILE *fsource, image_s *image, track_s *track)
fseek(fsource, 8, SEEK_CUR); // extra data (DJ 3.00.780 and up)
fread(&current_start_mark, 10, 1, fsource);
if (memcmp(TRACK_START_MARK, current_start_mark, 10)) printf( "Unsupported format: Could not find the track start mark");
if (memcmp(TRACK_START_MARK, current_start_mark, 10)) {
printf("CDI_read_track: Unsupported format: Could not find the track start mark\n");
return false;
}
fread(&current_start_mark, 10, 1, fsource);
if (memcmp(TRACK_START_MARK, current_start_mark, 10)) printf( "Unsupported format: Could not find the track start mark");
if (memcmp(TRACK_START_MARK, current_start_mark, 10)) {
printf("CDI_read_track: Unsupported format: Could not find the track start mark\n");
return false;
}
fseek(fsource, 4, SEEK_CUR);
fread(&track->filename_length, 1, 1, fsource);
@@ -80,20 +86,25 @@ void CDI_read_track (FILE *fsource, image_s *image, track_s *track)
case 1 : track->sector_size = 2336; break;
case 2 : track->sector_size = 2352; break;
case 4 : track->sector_size = 2448; break;
default: printf("Unsupported sector size. value %ld\n", track->sector_size_value);
break;
default:
printf("CDI_read_track: Unsupported sector size. value %ld\n", track->sector_size_value);
return false;
}
if (track->mode > 2) printf( "Unsupported format: Track mode not supported");
if (track->mode > 2) {
printf("CDI_read_track: Unsupported format: Track mode not supported\n");
return false;
}
fseek(fsource, 29, SEEK_CUR);
if (image->version != CDI_V2)
{
{
fseek(fsource, 5, SEEK_CUR);
fread(&temp_value, 4, 1, fsource);
if (temp_value == 0xffffffff)
fseek(fsource, 78, SEEK_CUR); // extra data (DJ 3.00.780 and up)
}
}
return true;
}
@@ -104,9 +115,9 @@ void CDI_skip_next_session (FILE *fsource, image_s *image)
if (image->version != CDI_V2) fseek(fsource, 1, SEEK_CUR);
}
void CDI_get_tracks (FILE *fsource, image_s *image)
bool CDI_get_tracks (FILE *fsource, image_s *image)
{
fread(&image->tracks, 2, 1, fsource);
return fread(&image->tracks, 2, 1, fsource) == 1;
}
bool CDI_init (FILE *fsource, image_s *image, const char *fsourcename)
@@ -121,8 +132,9 @@ bool CDI_init (FILE *fsource, image_s *image, const char *fsourcename)
}
fseek(fsource, image->length-8, SEEK_SET);
fread(&image->version, 4, 1, fsource);
fread(&image->header_offset, 4, 1, fsource);
if (fread(&image->version, 4, 1, fsource) != 1
|| fread(&image->header_offset, 4, 1, fsource) != 1)
return false;
if ((image->version != CDI_V2 && image->version != CDI_V3 && image->version != CDI_V35)
|| image->header_offset == 0)
@@ -133,7 +145,7 @@ bool CDI_init (FILE *fsource, image_s *image, const char *fsourcename)
return true;
}
void CDI_get_sessions (FILE *fsource, image_s *image)
bool CDI_get_sessions (FILE *fsource, image_s *image)
{
#ifndef DEBUG_CDI
if (image->version == CDI_V35)
@@ -144,6 +156,6 @@ void CDI_get_sessions (FILE *fsource, image_s *image)
#else
fseek(fsource, 0L, SEEK_SET);
#endif
fread(&image->sessions, 2, 1, fsource);
return fread(&image->sessions, 2, 1, fsource) == 1;
}
+3 -3
View File
@@ -38,9 +38,9 @@ typedef struct track_s
unsigned long ask_type(FILE *fsource, long header_position);
bool CDI_init(FILE *fsource, image_s *image, const char *fsourcename);
void CDI_get_sessions(FILE *fsource, image_s *image);
void CDI_get_tracks(FILE *fsource, image_s *image);
void CDI_read_track(FILE *fsource, image_s *image, track_s *track);
bool CDI_get_sessions(FILE *fsource, image_s *image);
bool CDI_get_tracks(FILE *fsource, image_s *image);
bool CDI_read_track(FILE *fsource, image_s *image, track_s *track);
void CDI_skip_next_session(FILE *fsource, image_s *image);
#endif
+1 -1
View File
@@ -56,7 +56,7 @@ public:
*/
#if defined(_WIN32)
# include "platform_windows.h"
#elif defined(__unix__) || defined(__APPLE__) || defined(__SWITCH__)
#elif defined(__unix__) || defined(__APPLE__) || defined(__SWITCH__) || defined(__HAIKU__)
# include "platform_linux.h"
#else
# error Unsupported platform
+1 -1
View File
@@ -4,7 +4,7 @@
* Use of this software is governed by the MIT license that can be found
* in the LICENSE file.
*/
#if defined(__unix__) || defined(__APPLE__) || defined(__SWITCH__)
#if defined(__unix__) || defined(__APPLE__) || defined(__SWITCH__) || defined(__HAIKU__)
#include "platform_linux.h"
#include <time.h>
+1 -1
View File
@@ -13,7 +13,7 @@
template<class T, int N> class RingBuffer
{
public:
RingBuffer<T, N>() :
RingBuffer() :
_head(0),
_tail(0),
_size(0) {
+1 -1
View File
@@ -13,7 +13,7 @@
template<class T, int N> class StaticBuffer
{
public:
StaticBuffer<T, N>() :
StaticBuffer() :
_size(0) {
}
+2 -2
View File
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
cmake_policy(VERSION 3.2)
cmake_minimum_required(VERSION 3.6 FATAL_ERROR)
cmake_policy(VERSION 3.6)
set(GLM_VERSION "0.9.9")
project(glm VERSION ${GLM_VERSION} LANGUAGES CXX)
Submodule core/deps/googletest added at e397860881.
-343
View File
@@ -1,343 +0,0 @@
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The Google C++ Testing and Mocking Framework (Google Test)
//
// This header file defines the public API for death tests. It is
// #included by gtest.h so a user doesn't need to include this
// directly.
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
#include "internal/gtest-death-test-internal.h"
namespace testing {
// This flag controls the style of death tests. Valid values are "threadsafe",
// meaning that the death test child process will re-execute the test binary
// from the start, running only a single death test, or "fast",
// meaning that the child process will execute the test logic immediately
// after forking.
GTEST_DECLARE_string_(death_test_style);
#if GTEST_HAS_DEATH_TEST
namespace internal {
// Returns a Boolean value indicating whether the caller is currently
// executing in the context of the death test child process. Tools such as
// Valgrind heap checkers may need this to modify their behavior in death
// tests. IMPORTANT: This is an internal utility. Using it may break the
// implementation of death tests. User code MUST NOT use it.
GTEST_API_ bool InDeathTestChild();
} // namespace internal
// The following macros are useful for writing death tests.
// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
// executed:
//
// 1. It generates a warning if there is more than one active
// thread. This is because it's safe to fork() or clone() only
// when there is a single thread.
//
// 2. The parent process clone()s a sub-process and runs the death
// test in it; the sub-process exits with code 0 at the end of the
// death test, if it hasn't exited already.
//
// 3. The parent process waits for the sub-process to terminate.
//
// 4. The parent process checks the exit code and error message of
// the sub-process.
//
// Examples:
//
// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
// for (int i = 0; i < 5; i++) {
// EXPECT_DEATH(server.ProcessRequest(i),
// "Invalid request .* in ProcessRequest()")
// << "Failed to die on request " << i;
// }
//
// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
//
// bool KilledBySIGHUP(int exit_code) {
// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
// }
//
// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
//
// On the regular expressions used in death tests:
//
// GOOGLETEST_CM0005 DO NOT DELETE
// On POSIX-compliant systems (*nix), we use the <regex.h> library,
// which uses the POSIX extended regex syntax.
//
// On other platforms (e.g. Windows or Mac), we only support a simple regex
// syntax implemented as part of Google Test. This limited
// implementation should be enough most of the time when writing
// death tests; though it lacks many features you can find in PCRE
// or POSIX extended regex syntax. For example, we don't support
// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
// repetition count ("x{5,7}"), among others.
//
// Below is the syntax that we do support. We chose it to be a
// subset of both PCRE and POSIX extended regex, so it's easy to
// learn wherever you come from. In the following: 'A' denotes a
// literal character, period (.), or a single \\ escape sequence;
// 'x' and 'y' denote regular expressions; 'm' and 'n' are for
// natural numbers.
//
// c matches any literal character c
// \\d matches any decimal digit
// \\D matches any character that's not a decimal digit
// \\f matches \f
// \\n matches \n
// \\r matches \r
// \\s matches any ASCII whitespace, including \n
// \\S matches any character that's not a whitespace
// \\t matches \t
// \\v matches \v
// \\w matches any letter, _, or decimal digit
// \\W matches any character that \\w doesn't match
// \\c matches any literal character c, which must be a punctuation
// . matches any single character except \n
// A? matches 0 or 1 occurrences of A
// A* matches 0 or many occurrences of A
// A+ matches 1 or many occurrences of A
// ^ matches the beginning of a string (not that of each line)
// $ matches the end of a string (not that of each line)
// xy matches x followed by y
//
// If you accidentally use PCRE or POSIX extended regex features
// not implemented by us, you will get a run-time failure. In that
// case, please try to rewrite your regular expression within the
// above syntax.
//
// This implementation is *not* meant to be as highly tuned or robust
// as a compiled regex library, but should perform well enough for a
// death test, which already incurs significant overhead by launching
// a child process.
//
// Known caveats:
//
// A "threadsafe" style death test obtains the path to the test
// program from argv[0] and re-executes it in the sub-process. For
// simplicity, the current implementation doesn't search the PATH
// when launching the sub-process. This means that the user must
// invoke the test program via a path that contains at least one
// path separator (e.g. path/to/foo_test and
// /absolute/path/to/bar_test are fine, but foo_test is not). This
// is rarely a problem as people usually don't put the test binary
// directory in PATH.
//
// Asserts that a given statement causes the program to exit, with an
// integer exit status that satisfies predicate, and emitting error output
// that matches regex.
# define ASSERT_EXIT(statement, predicate, regex) \
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
// Like ASSERT_EXIT, but continues on to successive tests in the
// test suite, if any:
# define EXPECT_EXIT(statement, predicate, regex) \
GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
// Asserts that a given statement causes the program to exit, either by
// explicitly exiting with a nonzero exit code or being killed by a
// signal, and emitting error output that matches regex.
# define ASSERT_DEATH(statement, regex) \
ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
// Like ASSERT_DEATH, but continues on to successive tests in the
// test suite, if any:
# define EXPECT_DEATH(statement, regex) \
EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
// Tests that an exit code describes a normal exit with a given exit code.
class GTEST_API_ ExitedWithCode {
public:
explicit ExitedWithCode(int exit_code);
bool operator()(int exit_status) const;
private:
// No implementation - assignment is unsupported.
void operator=(const ExitedWithCode& other);
const int exit_code_;
};
# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
// Tests that an exit code describes an exit due to termination by a
// given signal.
// GOOGLETEST_CM0006 DO NOT DELETE
class GTEST_API_ KilledBySignal {
public:
explicit KilledBySignal(int signum);
bool operator()(int exit_status) const;
private:
const int signum_;
};
# endif // !GTEST_OS_WINDOWS
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
// The death testing framework causes this to have interesting semantics,
// since the sideeffects of the call are only visible in opt mode, and not
// in debug mode.
//
// In practice, this can be used to test functions that utilize the
// LOG(DFATAL) macro using the following style:
//
// int DieInDebugOr12(int* sideeffect) {
// if (sideeffect) {
// *sideeffect = 12;
// }
// LOG(DFATAL) << "death";
// return 12;
// }
//
// TEST(TestSuite, TestDieOr12WorksInDgbAndOpt) {
// int sideeffect = 0;
// // Only asserts in dbg.
// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
//
// #ifdef NDEBUG
// // opt-mode has sideeffect visible.
// EXPECT_EQ(12, sideeffect);
// #else
// // dbg-mode no visible sideeffect.
// EXPECT_EQ(0, sideeffect);
// #endif
// }
//
// This will assert that DieInDebugReturn12InOpt() crashes in debug
// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
// appropriate fallback value (12 in this case) in opt mode. If you
// need to test that a function has appropriate side-effects in opt
// mode, include assertions against the side-effects. A general
// pattern for this is:
//
// EXPECT_DEBUG_DEATH({
// // Side-effects here will have an effect after this statement in
// // opt mode, but none in debug mode.
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
// }, "death");
//
# ifdef NDEBUG
# define EXPECT_DEBUG_DEATH(statement, regex) \
GTEST_EXECUTE_STATEMENT_(statement, regex)
# define ASSERT_DEBUG_DEATH(statement, regex) \
GTEST_EXECUTE_STATEMENT_(statement, regex)
# else
# define EXPECT_DEBUG_DEATH(statement, regex) \
EXPECT_DEATH(statement, regex)
# define ASSERT_DEBUG_DEATH(statement, regex) \
ASSERT_DEATH(statement, regex)
# endif // NDEBUG for EXPECT_DEBUG_DEATH
#endif // GTEST_HAS_DEATH_TEST
// This macro is used for implementing macros such as
// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
// death tests are not supported. Those macros must compile on such systems
// if and only if EXPECT_DEATH and ASSERT_DEATH compile with the same parameters
// on systems that support death tests. This allows one to write such a macro on
// a system that does not support death tests and be sure that it will compile
// on a death-test supporting system. It is exposed publicly so that systems
// that have death-tests with stricter requirements than GTEST_HAS_DEATH_TEST
// can write their own equivalent of EXPECT_DEATH_IF_SUPPORTED and
// ASSERT_DEATH_IF_SUPPORTED.
//
// Parameters:
// statement - A statement that a macro such as EXPECT_DEATH would test
// for program termination. This macro has to make sure this
// statement is compiled but not executed, to ensure that
// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
// parameter if and only if EXPECT_DEATH compiles with it.
// regex - A regex that a macro such as EXPECT_DEATH would use to test
// the output of statement. This parameter has to be
// compiled but not evaluated by this macro, to ensure that
// this macro only accepts expressions that a macro such as
// EXPECT_DEATH would accept.
// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
// and a return statement for ASSERT_DEATH_IF_SUPPORTED.
// This ensures that ASSERT_DEATH_IF_SUPPORTED will not
// compile inside functions where ASSERT_DEATH doesn't
// compile.
//
// The branch that has an always false condition is used to ensure that
// statement and regex are compiled (and thus syntactically correct) but
// never executed. The unreachable code macro protects the terminator
// statement from generating an 'unreachable code' warning in case
// statement unconditionally returns or throws. The Message constructor at
// the end allows the syntax of streaming additional messages into the
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
# define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_LOG_(WARNING) \
<< "Death tests are not supported on this platform.\n" \
<< "Statement '" #statement "' cannot be verified."; \
} else if (::testing::internal::AlwaysFalse()) { \
::testing::internal::RE::PartialMatch(".*", (regex)); \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
terminator; \
} else \
::testing::Message()
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
// death tests are supported; otherwise they just issue a warning. This is
// useful when you are combining death test assertions with normal test
// assertions in one test.
#if GTEST_HAS_DEATH_TEST
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
EXPECT_DEATH(statement, regex)
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
ASSERT_DEATH(statement, regex)
#else
# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, )
# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return)
#endif
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
-750
View File
@@ -1,750 +0,0 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// The Google C++ Testing and Mocking Framework (Google Test)
//
// This file implements just enough of the matcher interface to allow
// EXPECT_DEATH and friends to accept a matcher argument.
// IWYU pragma: private, include "testing/base/public/gunit.h"
// IWYU pragma: friend third_party/googletest/googlemock/.*
// IWYU pragma: friend third_party/googletest/googletest/.*
#ifndef GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
#define GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
#include <memory>
#include <ostream>
#include <string>
#include <type_traits>
#include "gtest-printers.h"
#include "internal/gtest-internal.h"
#include "internal/gtest-port.h"
// MSVC warning C5046 is new as of VS2017 version 15.8.
#if defined(_MSC_VER) && _MSC_VER >= 1915
#define GTEST_MAYBE_5046_ 5046
#else
#define GTEST_MAYBE_5046_
#endif
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
4251 GTEST_MAYBE_5046_ /* class A needs to have dll-interface to be used by
clients of class B */
/* Symbol involving type with internal linkage not defined */)
namespace testing {
// To implement a matcher Foo for type T, define:
// 1. a class FooMatcherImpl that implements the
// MatcherInterface<T> interface, and
// 2. a factory function that creates a Matcher<T> object from a
// FooMatcherImpl*.
//
// The two-level delegation design makes it possible to allow a user
// to write "v" instead of "Eq(v)" where a Matcher is expected, which
// is impossible if we pass matchers by pointers. It also eases
// ownership management as Matcher objects can now be copied like
// plain values.
// MatchResultListener is an abstract class. Its << operator can be
// used by a matcher to explain why a value matches or doesn't match.
//
class MatchResultListener {
public:
// Creates a listener object with the given underlying ostream. The
// listener does not own the ostream, and does not dereference it
// in the constructor or destructor.
explicit MatchResultListener(::std::ostream* os) : stream_(os) {}
virtual ~MatchResultListener() = 0; // Makes this class abstract.
// Streams x to the underlying ostream; does nothing if the ostream
// is NULL.
template <typename T>
MatchResultListener& operator<<(const T& x) {
if (stream_ != nullptr) *stream_ << x;
return *this;
}
// Returns the underlying ostream.
::std::ostream* stream() { return stream_; }
// Returns true if and only if the listener is interested in an explanation
// of the match result. A matcher's MatchAndExplain() method can use
// this information to avoid generating the explanation when no one
// intends to hear it.
bool IsInterested() const { return stream_ != nullptr; }
private:
::std::ostream* const stream_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener);
};
inline MatchResultListener::~MatchResultListener() {
}
// An instance of a subclass of this knows how to describe itself as a
// matcher.
class MatcherDescriberInterface {
public:
virtual ~MatcherDescriberInterface() {}
// Describes this matcher to an ostream. The function should print
// a verb phrase that describes the property a value matching this
// matcher should have. The subject of the verb phrase is the value
// being matched. For example, the DescribeTo() method of the Gt(7)
// matcher prints "is greater than 7".
virtual void DescribeTo(::std::ostream* os) const = 0;
// Describes the negation of this matcher to an ostream. For
// example, if the description of this matcher is "is greater than
// 7", the negated description could be "is not greater than 7".
// You are not required to override this when implementing
// MatcherInterface, but it is highly advised so that your matcher
// can produce good error messages.
virtual void DescribeNegationTo(::std::ostream* os) const {
*os << "not (";
DescribeTo(os);
*os << ")";
}
};
// The implementation of a matcher.
template <typename T>
class MatcherInterface : public MatcherDescriberInterface {
public:
// Returns true if and only if the matcher matches x; also explains the
// match result to 'listener' if necessary (see the next paragraph), in
// the form of a non-restrictive relative clause ("which ...",
// "whose ...", etc) that describes x. For example, the
// MatchAndExplain() method of the Pointee(...) matcher should
// generate an explanation like "which points to ...".
//
// Implementations of MatchAndExplain() should add an explanation of
// the match result *if and only if* they can provide additional
// information that's not already present (or not obvious) in the
// print-out of x and the matcher's description. Whether the match
// succeeds is not a factor in deciding whether an explanation is
// needed, as sometimes the caller needs to print a failure message
// when the match succeeds (e.g. when the matcher is used inside
// Not()).
//
// For example, a "has at least 10 elements" matcher should explain
// what the actual element count is, regardless of the match result,
// as it is useful information to the reader; on the other hand, an
// "is empty" matcher probably only needs to explain what the actual
// size is when the match fails, as it's redundant to say that the
// size is 0 when the value is already known to be empty.
//
// You should override this method when defining a new matcher.
//
// It's the responsibility of the caller (Google Test) to guarantee
// that 'listener' is not NULL. This helps to simplify a matcher's
// implementation when it doesn't care about the performance, as it
// can talk to 'listener' without checking its validity first.
// However, in order to implement dummy listeners efficiently,
// listener->stream() may be NULL.
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
// Inherits these methods from MatcherDescriberInterface:
// virtual void DescribeTo(::std::ostream* os) const = 0;
// virtual void DescribeNegationTo(::std::ostream* os) const;
};
namespace internal {
// Converts a MatcherInterface<T> to a MatcherInterface<const T&>.
template <typename T>
class MatcherInterfaceAdapter : public MatcherInterface<const T&> {
public:
explicit MatcherInterfaceAdapter(const MatcherInterface<T>* impl)
: impl_(impl) {}
~MatcherInterfaceAdapter() override { delete impl_; }
void DescribeTo(::std::ostream* os) const override { impl_->DescribeTo(os); }
void DescribeNegationTo(::std::ostream* os) const override {
impl_->DescribeNegationTo(os);
}
bool MatchAndExplain(const T& x,
MatchResultListener* listener) const override {
return impl_->MatchAndExplain(x, listener);
}
private:
const MatcherInterface<T>* const impl_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(MatcherInterfaceAdapter);
};
struct AnyEq {
template <typename A, typename B>
bool operator()(const A& a, const B& b) const { return a == b; }
};
struct AnyNe {
template <typename A, typename B>
bool operator()(const A& a, const B& b) const { return a != b; }
};
struct AnyLt {
template <typename A, typename B>
bool operator()(const A& a, const B& b) const { return a < b; }
};
struct AnyGt {
template <typename A, typename B>
bool operator()(const A& a, const B& b) const { return a > b; }
};
struct AnyLe {
template <typename A, typename B>
bool operator()(const A& a, const B& b) const { return a <= b; }
};
struct AnyGe {
template <typename A, typename B>
bool operator()(const A& a, const B& b) const { return a >= b; }
};
// A match result listener that ignores the explanation.
class DummyMatchResultListener : public MatchResultListener {
public:
DummyMatchResultListener() : MatchResultListener(nullptr) {}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener);
};
// A match result listener that forwards the explanation to a given
// ostream. The difference between this and MatchResultListener is
// that the former is concrete.
class StreamMatchResultListener : public MatchResultListener {
public:
explicit StreamMatchResultListener(::std::ostream* os)
: MatchResultListener(os) {}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener);
};
// An internal class for implementing Matcher<T>, which will derive
// from it. We put functionalities common to all Matcher<T>
// specializations here to avoid code duplication.
template <typename T>
class MatcherBase {
public:
// Returns true if and only if the matcher matches x; also explains the
// match result to 'listener'.
bool MatchAndExplain(const T& x, MatchResultListener* listener) const {
return impl_->MatchAndExplain(x, listener);
}
// Returns true if and only if this matcher matches x.
bool Matches(const T& x) const {
DummyMatchResultListener dummy;
return MatchAndExplain(x, &dummy);
}
// Describes this matcher to an ostream.
void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
// Describes the negation of this matcher to an ostream.
void DescribeNegationTo(::std::ostream* os) const {
impl_->DescribeNegationTo(os);
}
// Explains why x matches, or doesn't match, the matcher.
void ExplainMatchResultTo(const T& x, ::std::ostream* os) const {
StreamMatchResultListener listener(os);
MatchAndExplain(x, &listener);
}
// Returns the describer for this matcher object; retains ownership
// of the describer, which is only guaranteed to be alive when
// this matcher object is alive.
const MatcherDescriberInterface* GetDescriber() const {
return impl_.get();
}
protected:
MatcherBase() {}
// Constructs a matcher from its implementation.
explicit MatcherBase(const MatcherInterface<const T&>* impl) : impl_(impl) {}
template <typename U>
explicit MatcherBase(
const MatcherInterface<U>* impl,
typename std::enable_if<!std::is_same<U, const U&>::value>::type* =
nullptr)
: impl_(new internal::MatcherInterfaceAdapter<U>(impl)) {}
MatcherBase(const MatcherBase&) = default;
MatcherBase& operator=(const MatcherBase&) = default;
MatcherBase(MatcherBase&&) = default;
MatcherBase& operator=(MatcherBase&&) = default;
virtual ~MatcherBase() {}
private:
std::shared_ptr<const MatcherInterface<const T&>> impl_;
};
} // namespace internal
// A Matcher<T> is a copyable and IMMUTABLE (except by assignment)
// object that can check whether a value of type T matches. The
// implementation of Matcher<T> is just a std::shared_ptr to const
// MatcherInterface<T>. Don't inherit from Matcher!
template <typename T>
class Matcher : public internal::MatcherBase<T> {
public:
// Constructs a null matcher. Needed for storing Matcher objects in STL
// containers. A default-constructed matcher is not yet initialized. You
// cannot use it until a valid value has been assigned to it.
explicit Matcher() {} // NOLINT
// Constructs a matcher from its implementation.
explicit Matcher(const MatcherInterface<const T&>* impl)
: internal::MatcherBase<T>(impl) {}
template <typename U>
explicit Matcher(
const MatcherInterface<U>* impl,
typename std::enable_if<!std::is_same<U, const U&>::value>::type* =
nullptr)
: internal::MatcherBase<T>(impl) {}
// Implicit constructor here allows people to write
// EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes
Matcher(T value); // NOLINT
};
// The following two specializations allow the user to write str
// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string
// matcher is expected.
template <>
class GTEST_API_ Matcher<const std::string&>
: public internal::MatcherBase<const std::string&> {
public:
Matcher() {}
explicit Matcher(const MatcherInterface<const std::string&>* impl)
: internal::MatcherBase<const std::string&>(impl) {}
// Allows the user to write str instead of Eq(str) sometimes, where
// str is a std::string object.
Matcher(const std::string& s); // NOLINT
// Allows the user to write "foo" instead of Eq("foo") sometimes.
Matcher(const char* s); // NOLINT
};
template <>
class GTEST_API_ Matcher<std::string>
: public internal::MatcherBase<std::string> {
public:
Matcher() {}
explicit Matcher(const MatcherInterface<const std::string&>* impl)
: internal::MatcherBase<std::string>(impl) {}
explicit Matcher(const MatcherInterface<std::string>* impl)
: internal::MatcherBase<std::string>(impl) {}
// Allows the user to write str instead of Eq(str) sometimes, where
// str is a string object.
Matcher(const std::string& s); // NOLINT
// Allows the user to write "foo" instead of Eq("foo") sometimes.
Matcher(const char* s); // NOLINT
};
#if GTEST_HAS_ABSL
// The following two specializations allow the user to write str
// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view
// matcher is expected.
template <>
class GTEST_API_ Matcher<const absl::string_view&>
: public internal::MatcherBase<const absl::string_view&> {
public:
Matcher() {}
explicit Matcher(const MatcherInterface<const absl::string_view&>* impl)
: internal::MatcherBase<const absl::string_view&>(impl) {}
// Allows the user to write str instead of Eq(str) sometimes, where
// str is a std::string object.
Matcher(const std::string& s); // NOLINT
// Allows the user to write "foo" instead of Eq("foo") sometimes.
Matcher(const char* s); // NOLINT
// Allows the user to pass absl::string_views directly.
Matcher(absl::string_view s); // NOLINT
};
template <>
class GTEST_API_ Matcher<absl::string_view>
: public internal::MatcherBase<absl::string_view> {
public:
Matcher() {}
explicit Matcher(const MatcherInterface<const absl::string_view&>* impl)
: internal::MatcherBase<absl::string_view>(impl) {}
explicit Matcher(const MatcherInterface<absl::string_view>* impl)
: internal::MatcherBase<absl::string_view>(impl) {}
// Allows the user to write str instead of Eq(str) sometimes, where
// str is a std::string object.
Matcher(const std::string& s); // NOLINT
// Allows the user to write "foo" instead of Eq("foo") sometimes.
Matcher(const char* s); // NOLINT
// Allows the user to pass absl::string_views directly.
Matcher(absl::string_view s); // NOLINT
};
#endif // GTEST_HAS_ABSL
// Prints a matcher in a human-readable format.
template <typename T>
std::ostream& operator<<(std::ostream& os, const Matcher<T>& matcher) {
matcher.DescribeTo(&os);
return os;
}
// The PolymorphicMatcher class template makes it easy to implement a
// polymorphic matcher (i.e. a matcher that can match values of more
// than one type, e.g. Eq(n) and NotNull()).
//
// To define a polymorphic matcher, a user should provide an Impl
// class that has a DescribeTo() method and a DescribeNegationTo()
// method, and define a member function (or member function template)
//
// bool MatchAndExplain(const Value& value,
// MatchResultListener* listener) const;
//
// See the definition of NotNull() for a complete example.
template <class Impl>
class PolymorphicMatcher {
public:
explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
// Returns a mutable reference to the underlying matcher
// implementation object.
Impl& mutable_impl() { return impl_; }
// Returns an immutable reference to the underlying matcher
// implementation object.
const Impl& impl() const { return impl_; }
template <typename T>
operator Matcher<T>() const {
return Matcher<T>(new MonomorphicImpl<const T&>(impl_));
}
private:
template <typename T>
class MonomorphicImpl : public MatcherInterface<T> {
public:
explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
void DescribeTo(::std::ostream* os) const override { impl_.DescribeTo(os); }
void DescribeNegationTo(::std::ostream* os) const override {
impl_.DescribeNegationTo(os);
}
bool MatchAndExplain(T x, MatchResultListener* listener) const override {
return impl_.MatchAndExplain(x, listener);
}
private:
const Impl impl_;
};
Impl impl_;
};
// Creates a matcher from its implementation.
// DEPRECATED: Especially in the generic code, prefer:
// Matcher<T>(new MyMatcherImpl<const T&>(...));
//
// MakeMatcher may create a Matcher that accepts its argument by value, which
// leads to unnecessary copies & lack of support for non-copyable types.
template <typename T>
inline Matcher<T> MakeMatcher(const MatcherInterface<T>* impl) {
return Matcher<T>(impl);
}
// Creates a polymorphic matcher from its implementation. This is
// easier to use than the PolymorphicMatcher<Impl> constructor as it
// doesn't require you to explicitly write the template argument, e.g.
//
// MakePolymorphicMatcher(foo);
// vs
// PolymorphicMatcher<TypeOfFoo>(foo);
template <class Impl>
inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
return PolymorphicMatcher<Impl>(impl);
}
namespace internal {
// Implements a matcher that compares a given value with a
// pre-supplied value using one of the ==, <=, <, etc, operators. The
// two values being compared don't have to have the same type.
//
// The matcher defined here is polymorphic (for example, Eq(5) can be
// used to match an int, a short, a double, etc). Therefore we use
// a template type conversion operator in the implementation.
//
// The following template definition assumes that the Rhs parameter is
// a "bare" type (i.e. neither 'const T' nor 'T&').
template <typename D, typename Rhs, typename Op>
class ComparisonBase {
public:
explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {}
template <typename Lhs>
operator Matcher<Lhs>() const {
return Matcher<Lhs>(new Impl<const Lhs&>(rhs_));
}
private:
template <typename T>
static const T& Unwrap(const T& v) { return v; }
template <typename T>
static const T& Unwrap(std::reference_wrapper<T> v) { return v; }
template <typename Lhs, typename = Rhs>
class Impl : public MatcherInterface<Lhs> {
public:
explicit Impl(const Rhs& rhs) : rhs_(rhs) {}
bool MatchAndExplain(Lhs lhs,
MatchResultListener* /* listener */) const override {
return Op()(lhs, Unwrap(rhs_));
}
void DescribeTo(::std::ostream* os) const override {
*os << D::Desc() << " ";
UniversalPrint(Unwrap(rhs_), os);
}
void DescribeNegationTo(::std::ostream* os) const override {
*os << D::NegatedDesc() << " ";
UniversalPrint(Unwrap(rhs_), os);
}
private:
Rhs rhs_;
};
Rhs rhs_;
};
template <typename Rhs>
class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> {
public:
explicit EqMatcher(const Rhs& rhs)
: ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) { }
static const char* Desc() { return "is equal to"; }
static const char* NegatedDesc() { return "isn't equal to"; }
};
template <typename Rhs>
class NeMatcher : public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> {
public:
explicit NeMatcher(const Rhs& rhs)
: ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) { }
static const char* Desc() { return "isn't equal to"; }
static const char* NegatedDesc() { return "is equal to"; }
};
template <typename Rhs>
class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> {
public:
explicit LtMatcher(const Rhs& rhs)
: ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) { }
static const char* Desc() { return "is <"; }
static const char* NegatedDesc() { return "isn't <"; }
};
template <typename Rhs>
class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> {
public:
explicit GtMatcher(const Rhs& rhs)
: ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) { }
static const char* Desc() { return "is >"; }
static const char* NegatedDesc() { return "isn't >"; }
};
template <typename Rhs>
class LeMatcher : public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> {
public:
explicit LeMatcher(const Rhs& rhs)
: ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) { }
static const char* Desc() { return "is <="; }
static const char* NegatedDesc() { return "isn't <="; }
};
template <typename Rhs>
class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
public:
explicit GeMatcher(const Rhs& rhs)
: ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) { }
static const char* Desc() { return "is >="; }
static const char* NegatedDesc() { return "isn't >="; }
};
// Implements polymorphic matchers MatchesRegex(regex) and
// ContainsRegex(regex), which can be used as a Matcher<T> as long as
// T can be converted to a string.
class MatchesRegexMatcher {
public:
MatchesRegexMatcher(const RE* regex, bool full_match)
: regex_(regex), full_match_(full_match) {}
#if GTEST_HAS_ABSL
bool MatchAndExplain(const absl::string_view& s,
MatchResultListener* listener) const {
return MatchAndExplain(std::string(s), listener);
}
#endif // GTEST_HAS_ABSL
// Accepts pointer types, particularly:
// const char*
// char*
// const wchar_t*
// wchar_t*
template <typename CharType>
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
return s != nullptr && MatchAndExplain(std::string(s), listener);
}
// Matches anything that can convert to std::string.
//
// This is a template, not just a plain function with const std::string&,
// because absl::string_view has some interfering non-explicit constructors.
template <class MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const {
const std::string& s2(s);
return full_match_ ? RE::FullMatch(s2, *regex_)
: RE::PartialMatch(s2, *regex_);
}
void DescribeTo(::std::ostream* os) const {
*os << (full_match_ ? "matches" : "contains") << " regular expression ";
UniversalPrinter<std::string>::Print(regex_->pattern(), os);
}
void DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't " << (full_match_ ? "match" : "contain")
<< " regular expression ";
UniversalPrinter<std::string>::Print(regex_->pattern(), os);
}
private:
const std::shared_ptr<const RE> regex_;
const bool full_match_;
};
} // namespace internal
// Matches a string that fully matches regular expression 'regex'.
// The matcher takes ownership of 'regex'.
inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
const internal::RE* regex) {
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
}
inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
const std::string& regex) {
return MatchesRegex(new internal::RE(regex));
}
// Matches a string that contains regular expression 'regex'.
// The matcher takes ownership of 'regex'.
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
const internal::RE* regex) {
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
}
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
const std::string& regex) {
return ContainsRegex(new internal::RE(regex));
}
// Creates a polymorphic matcher that matches anything equal to x.
// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
// wouldn't compile.
template <typename T>
inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
// Constructs a Matcher<T> from a 'value' of type T. The constructed
// matcher matches any value that's equal to 'value'.
template <typename T>
Matcher<T>::Matcher(T value) { *this = Eq(value); }
// Creates a monomorphic matcher that matches anything with type Lhs
// and equal to rhs. A user may need to use this instead of Eq(...)
// in order to resolve an overloading ambiguity.
//
// TypedEq<T>(x) is just a convenient short-hand for Matcher<T>(Eq(x))
// or Matcher<T>(x), but more readable than the latter.
//
// We could define similar monomorphic matchers for other comparison
// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do
// it yet as those are used much less than Eq() in practice. A user
// can always write Matcher<T>(Lt(5)) to be explicit about the type,
// for example.
template <typename Lhs, typename Rhs>
inline Matcher<Lhs> TypedEq(const Rhs& rhs) { return Eq(rhs); }
// Creates a polymorphic matcher that matches anything >= x.
template <typename Rhs>
inline internal::GeMatcher<Rhs> Ge(Rhs x) {
return internal::GeMatcher<Rhs>(x);
}
// Creates a polymorphic matcher that matches anything > x.
template <typename Rhs>
inline internal::GtMatcher<Rhs> Gt(Rhs x) {
return internal::GtMatcher<Rhs>(x);
}
// Creates a polymorphic matcher that matches anything <= x.
template <typename Rhs>
inline internal::LeMatcher<Rhs> Le(Rhs x) {
return internal::LeMatcher<Rhs>(x);
}
// Creates a polymorphic matcher that matches anything < x.
template <typename Rhs>
inline internal::LtMatcher<Rhs> Lt(Rhs x) {
return internal::LtMatcher<Rhs>(x);
}
// Creates a polymorphic matcher that matches anything != x.
template <typename Rhs>
inline internal::NeMatcher<Rhs> Ne(Rhs x) {
return internal::NeMatcher<Rhs>(x);
}
} // namespace testing
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046
#endif // GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
-219
View File
@@ -1,219 +0,0 @@
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The Google C++ Testing and Mocking Framework (Google Test)
//
// This header file defines the Message class.
//
// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
// leave some internal implementation details in this header file.
// They are clearly marked by comments like this:
//
// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
//
// Such code is NOT meant to be used by a user directly, and is subject
// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
// program!
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
#include <limits>
#include <memory>
#include <sstream>
#include "internal/gtest-port.h"
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
/* class A needs to have dll-interface to be used by clients of class B */)
// Ensures that there is at least one operator<< in the global namespace.
// See Message& operator<<(...) below for why.
void operator<<(const testing::internal::Secret&, int);
namespace testing {
// The Message class works like an ostream repeater.
//
// Typical usage:
//
// 1. You stream a bunch of values to a Message object.
// It will remember the text in a stringstream.
// 2. Then you stream the Message object to an ostream.
// This causes the text in the Message to be streamed
// to the ostream.
//
// For example;
//
// testing::Message foo;
// foo << 1 << " != " << 2;
// std::cout << foo;
//
// will print "1 != 2".
//
// Message is not intended to be inherited from. In particular, its
// destructor is not virtual.
//
// Note that stringstream behaves differently in gcc and in MSVC. You
// can stream a NULL char pointer to it in the former, but not in the
// latter (it causes an access violation if you do). The Message
// class hides this difference by treating a NULL char pointer as
// "(null)".
class GTEST_API_ Message {
private:
// The type of basic IO manipulators (endl, ends, and flush) for
// narrow streams.
typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
public:
// Constructs an empty Message.
Message();
// Copy constructor.
Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
*ss_ << msg.GetString();
}
// Constructs a Message from a C-string.
explicit Message(const char* str) : ss_(new ::std::stringstream) {
*ss_ << str;
}
// Streams a non-pointer value to this object.
template <typename T>
inline Message& operator <<(const T& val) {
// Some libraries overload << for STL containers. These
// overloads are defined in the global namespace instead of ::std.
//
// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
// overloads are visible in either the std namespace or the global
// namespace, but not other namespaces, including the testing
// namespace which Google Test's Message class is in.
//
// To allow STL containers (and other types that has a << operator
// defined in the global namespace) to be used in Google Test
// assertions, testing::Message must access the custom << operator
// from the global namespace. With this using declaration,
// overloads of << defined in the global namespace and those
// visible via Koenig lookup are both exposed in this function.
using ::operator <<;
*ss_ << val;
return *this;
}
// Streams a pointer value to this object.
//
// This function is an overload of the previous one. When you
// stream a pointer to a Message, this definition will be used as it
// is more specialized. (The C++ Standard, section
// [temp.func.order].) If you stream a non-pointer, then the
// previous definition will be used.
//
// The reason for this overload is that streaming a NULL pointer to
// ostream is undefined behavior. Depending on the compiler, you
// may get "0", "(nil)", "(null)", or an access violation. To
// ensure consistent result across compilers, we always treat NULL
// as "(null)".
template <typename T>
inline Message& operator <<(T* const& pointer) { // NOLINT
if (pointer == nullptr) {
*ss_ << "(null)";
} else {
*ss_ << pointer;
}
return *this;
}
// Since the basic IO manipulators are overloaded for both narrow
// and wide streams, we have to provide this specialized definition
// of operator <<, even though its body is the same as the
// templatized version above. Without this definition, streaming
// endl or other basic IO manipulators to Message will confuse the
// compiler.
Message& operator <<(BasicNarrowIoManip val) {
*ss_ << val;
return *this;
}
// Instead of 1/0, we want to see true/false for bool values.
Message& operator <<(bool b) {
return *this << (b ? "true" : "false");
}
// These two overloads allow streaming a wide C string to a Message
// using the UTF-8 encoding.
Message& operator <<(const wchar_t* wide_c_str);
Message& operator <<(wchar_t* wide_c_str);
#if GTEST_HAS_STD_WSTRING
// Converts the given wide string to a narrow string using the UTF-8
// encoding, and streams the result to this Message object.
Message& operator <<(const ::std::wstring& wstr);
#endif // GTEST_HAS_STD_WSTRING
// Gets the text streamed to this object so far as an std::string.
// Each '\0' character in the buffer is replaced with "\\0".
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
std::string GetString() const;
private:
// We'll hold the text streamed to this object here.
const std::unique_ptr< ::std::stringstream> ss_;
// We declare (but don't implement) this to prevent the compiler
// from implementing the assignment operator.
void operator=(const Message&);
};
// Streams a Message to an ostream.
inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
return os << sb.GetString();
}
namespace internal {
// Converts a streamable value to an std::string. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
// ::std::string, ::wstring, or ::std::wstring object, each NUL
// character in it is replaced with "\\0".
template <typename T>
std::string StreamableToString(const T& streamable) {
return (Message() << streamable).GetString();
}
} // namespace internal
} // namespace testing
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
-514
View File
@@ -1,514 +0,0 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Macros and functions for implementing parameterized tests
// in Google C++ Testing and Mocking Framework (Google Test)
//
// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
//
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
// Value-parameterized tests allow you to test your code with different
// parameters without writing multiple copies of the same test.
//
// Here is how you use value-parameterized tests:
#if 0
// To write value-parameterized tests, first you should define a fixture
// class. It is usually derived from testing::TestWithParam<T> (see below for
// another inheritance scheme that's sometimes useful in more complicated
// class hierarchies), where the type of your parameter values.
// TestWithParam<T> is itself derived from testing::Test. T can be any
// copyable type. If it's a raw pointer, you are responsible for managing the
// lifespan of the pointed values.
class FooTest : public ::testing::TestWithParam<const char*> {
// You can implement all the usual class fixture members here.
};
// Then, use the TEST_P macro to define as many parameterized tests
// for this fixture as you want. The _P suffix is for "parameterized"
// or "pattern", whichever you prefer to think. The arguments to the
// TEST_P macro are the test_suite_name and test_case (both which must be
// non-empty) that will form the test name.
TEST_P(FooTest, DoesBlah) {
// Inside a test, access the test parameter with the GetParam() method
// of the TestWithParam<T> class:
EXPECT_TRUE(foo.Blah(GetParam()));
...
}
TEST_P(FooTest, HasBlahBlah) {
...
}
// Finally, you can use INSTANTIATE_TEST_SUITE_P to instantiate the test
// case with any set of parameters you want. Google Test defines a number
// of functions for generating test parameters. They return what we call
// (surprise!) parameter generators. Here is a summary of them, which
// are all in the testing namespace:
//
//
// Range(begin, end [, step]) - Yields values {begin, begin+step,
// begin+step+step, ...}. The values do not
// include end. step defaults to 1.
// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}.
// ValuesIn(container) - Yields values from a C-style array, an STL
// ValuesIn(begin,end) container, or an iterator range [begin, end).
// Bool() - Yields sequence {false, true}.
// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product
// for the math savvy) of the values generated
// by the N generators.
//
// For more details, see comments at the definitions of these functions below
// in this file.
//
// The following statement will instantiate tests from the FooTest test suite
// each with parameter values "meeny", "miny", and "moe".
INSTANTIATE_TEST_SUITE_P(InstantiationName,
FooTest,
Values("meeny", "miny", "moe"));
// To distinguish different instances of the pattern, (yes, you
// can instantiate it more than once) the first argument to the
// INSTANTIATE_TEST_SUITE_P macro is a prefix (which must be non-empty) that
// will be added to the actual test suite name. Remember to pick unique prefixes
// for different instantiations. The tests from the instantiation above will
// have these names:
//
// * InstantiationName/FooTest.DoesBlah/0 for "meeny"
// * InstantiationName/FooTest.DoesBlah/1 for "miny"
// * InstantiationName/FooTest.DoesBlah/2 for "moe"
// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
// * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
// * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
//
// You can use these names in --gtest_filter.
//
// This statement will instantiate all tests from FooTest again, each
// with parameter values "cat" and "dog":
const char* pets[] = {"cat", "dog"};
INSTANTIATE_TEST_SUITE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
// The tests from the instantiation above will have these names:
//
// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
//
// Please note that INSTANTIATE_TEST_SUITE_P will instantiate all tests
// in the given test suite, whether their definitions come before or
// AFTER the INSTANTIATE_TEST_SUITE_P statement.
//
// Please also note that generator expressions (including parameters to the
// generators) are evaluated in InitGoogleTest(), after main() has started.
// This allows the user on one hand, to adjust generator parameters in order
// to dynamically determine a set of tests to run and on the other hand,
// give the user a chance to inspect the generated tests with Google Test
// reflection API before RUN_ALL_TESTS() is executed.
//
// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
// for more examples.
//
// In the future, we plan to publish the API for defining new parameter
// generators. But for now this interface remains part of the internal
// implementation and is subject to change.
//
//
// A parameterized test fixture must be derived from testing::Test and from
// testing::WithParamInterface<T>, where T is the type of the parameter
// values. Inheriting from TestWithParam<T> satisfies that requirement because
// TestWithParam<T> inherits from both Test and WithParamInterface. In more
// complicated hierarchies, however, it is occasionally useful to inherit
// separately from Test and WithParamInterface. For example:
class BaseTest : public ::testing::Test {
// You can inherit all the usual members for a non-parameterized test
// fixture here.
};
class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
// The usual test fixture members go here too.
};
TEST_F(BaseTest, HasFoo) {
// This is an ordinary non-parameterized test.
}
TEST_P(DerivedTest, DoesBlah) {
// GetParam works just the same here as if you inherit from TestWithParam.
EXPECT_TRUE(foo.Blah(GetParam()));
}
#endif // 0
#include <iterator>
#include <utility>
#include "internal/gtest-internal.h"
#include "internal/gtest-param-util.h"
#include "internal/gtest-port.h"
namespace testing {
// Functions producing parameter generators.
//
// Google Test uses these generators to produce parameters for value-
// parameterized tests. When a parameterized test suite is instantiated
// with a particular generator, Google Test creates and runs tests
// for each element in the sequence produced by the generator.
//
// In the following sample, tests from test suite FooTest are instantiated
// each three times with parameter values 3, 5, and 8:
//
// class FooTest : public TestWithParam<int> { ... };
//
// TEST_P(FooTest, TestThis) {
// }
// TEST_P(FooTest, TestThat) {
// }
// INSTANTIATE_TEST_SUITE_P(TestSequence, FooTest, Values(3, 5, 8));
//
// Range() returns generators providing sequences of values in a range.
//
// Synopsis:
// Range(start, end)
// - returns a generator producing a sequence of values {start, start+1,
// start+2, ..., }.
// Range(start, end, step)
// - returns a generator producing a sequence of values {start, start+step,
// start+step+step, ..., }.
// Notes:
// * The generated sequences never include end. For example, Range(1, 5)
// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
// returns a generator producing {1, 3, 5, 7}.
// * start and end must have the same type. That type may be any integral or
// floating-point type or a user defined type satisfying these conditions:
// * It must be assignable (have operator=() defined).
// * It must have operator+() (operator+(int-compatible type) for
// two-operand version).
// * It must have operator<() defined.
// Elements in the resulting sequences will also have that type.
// * Condition start < end must be satisfied in order for resulting sequences
// to contain any elements.
//
template <typename T, typename IncrementT>
internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
return internal::ParamGenerator<T>(
new internal::RangeGenerator<T, IncrementT>(start, end, step));
}
template <typename T>
internal::ParamGenerator<T> Range(T start, T end) {
return Range(start, end, 1);
}
// ValuesIn() function allows generation of tests with parameters coming from
// a container.
//
// Synopsis:
// ValuesIn(const T (&array)[N])
// - returns a generator producing sequences with elements from
// a C-style array.
// ValuesIn(const Container& container)
// - returns a generator producing sequences with elements from
// an STL-style container.
// ValuesIn(Iterator begin, Iterator end)
// - returns a generator producing sequences with elements from
// a range [begin, end) defined by a pair of STL-style iterators. These
// iterators can also be plain C pointers.
//
// Please note that ValuesIn copies the values from the containers
// passed in and keeps them to generate tests in RUN_ALL_TESTS().
//
// Examples:
//
// This instantiates tests from test suite StringTest
// each with C-string values of "foo", "bar", and "baz":
//
// const char* strings[] = {"foo", "bar", "baz"};
// INSTANTIATE_TEST_SUITE_P(StringSequence, StringTest, ValuesIn(strings));
//
// This instantiates tests from test suite StlStringTest
// each with STL strings with values "a" and "b":
//
// ::std::vector< ::std::string> GetParameterStrings() {
// ::std::vector< ::std::string> v;
// v.push_back("a");
// v.push_back("b");
// return v;
// }
//
// INSTANTIATE_TEST_SUITE_P(CharSequence,
// StlStringTest,
// ValuesIn(GetParameterStrings()));
//
//
// This will also instantiate tests from CharTest
// each with parameter values 'a' and 'b':
//
// ::std::list<char> GetParameterChars() {
// ::std::list<char> list;
// list.push_back('a');
// list.push_back('b');
// return list;
// }
// ::std::list<char> l = GetParameterChars();
// INSTANTIATE_TEST_SUITE_P(CharSequence2,
// CharTest,
// ValuesIn(l.begin(), l.end()));
//
template <typename ForwardIterator>
internal::ParamGenerator<
typename std::iterator_traits<ForwardIterator>::value_type>
ValuesIn(ForwardIterator begin, ForwardIterator end) {
typedef typename std::iterator_traits<ForwardIterator>::value_type ParamType;
return internal::ParamGenerator<ParamType>(
new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
}
template <typename T, size_t N>
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
return ValuesIn(array, array + N);
}
template <class Container>
internal::ParamGenerator<typename Container::value_type> ValuesIn(
const Container& container) {
return ValuesIn(container.begin(), container.end());
}
// Values() allows generating tests from explicitly specified list of
// parameters.
//
// Synopsis:
// Values(T v1, T v2, ..., T vN)
// - returns a generator producing sequences with elements v1, v2, ..., vN.
//
// For example, this instantiates tests from test suite BarTest each
// with values "one", "two", and "three":
//
// INSTANTIATE_TEST_SUITE_P(NumSequence,
// BarTest,
// Values("one", "two", "three"));
//
// This instantiates tests from test suite BazTest each with values 1, 2, 3.5.
// The exact type of values will depend on the type of parameter in BazTest.
//
// INSTANTIATE_TEST_SUITE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
//
//
template <typename... T>
internal::ValueArray<T...> Values(T... v) {
return internal::ValueArray<T...>(std::move(v)...);
}
// Bool() allows generating tests with parameters in a set of (false, true).
//
// Synopsis:
// Bool()
// - returns a generator producing sequences with elements {false, true}.
//
// It is useful when testing code that depends on Boolean flags. Combinations
// of multiple flags can be tested when several Bool()'s are combined using
// Combine() function.
//
// In the following example all tests in the test suite FlagDependentTest
// will be instantiated twice with parameters false and true.
//
// class FlagDependentTest : public testing::TestWithParam<bool> {
// virtual void SetUp() {
// external_flag = GetParam();
// }
// }
// INSTANTIATE_TEST_SUITE_P(BoolSequence, FlagDependentTest, Bool());
//
inline internal::ParamGenerator<bool> Bool() {
return Values(false, true);
}
// Combine() allows the user to combine two or more sequences to produce
// values of a Cartesian product of those sequences' elements.
//
// Synopsis:
// Combine(gen1, gen2, ..., genN)
// - returns a generator producing sequences with elements coming from
// the Cartesian product of elements from the sequences generated by
// gen1, gen2, ..., genN. The sequence elements will have a type of
// std::tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
// of elements from sequences produces by gen1, gen2, ..., genN.
//
// Combine can have up to 10 arguments.
//
// Example:
//
// This will instantiate tests in test suite AnimalTest each one with
// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
// tuple("dog", BLACK), and tuple("dog", WHITE):
//
// enum Color { BLACK, GRAY, WHITE };
// class AnimalTest
// : public testing::TestWithParam<std::tuple<const char*, Color> > {...};
//
// TEST_P(AnimalTest, AnimalLooksNice) {...}
//
// INSTANTIATE_TEST_SUITE_P(AnimalVariations, AnimalTest,
// Combine(Values("cat", "dog"),
// Values(BLACK, WHITE)));
//
// This will instantiate tests in FlagDependentTest with all variations of two
// Boolean flags:
//
// class FlagDependentTest
// : public testing::TestWithParam<std::tuple<bool, bool> > {
// virtual void SetUp() {
// // Assigns external_flag_1 and external_flag_2 values from the tuple.
// std::tie(external_flag_1, external_flag_2) = GetParam();
// }
// };
//
// TEST_P(FlagDependentTest, TestFeature1) {
// // Test your code using external_flag_1 and external_flag_2 here.
// }
// INSTANTIATE_TEST_SUITE_P(TwoBoolSequence, FlagDependentTest,
// Combine(Bool(), Bool()));
//
template <typename... Generator>
internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
return internal::CartesianProductHolder<Generator...>(g...);
}
#define TEST_P(test_suite_name, test_name) \
static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \
"test_suite_name must not be empty"); \
static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \
"test_name must not be empty"); \
class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
: public test_suite_name { \
public: \
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \
void TestBody() override; \
\
private: \
static int AddToRegistry() { \
::testing::UnitTest::GetInstance() \
->parameterized_test_registry() \
.GetTestSuitePatternHolder<test_suite_name>( \
GTEST_STRINGIFY_(test_suite_name), \
::testing::internal::CodeLocation(__FILE__, __LINE__)) \
->AddTestPattern( \
GTEST_STRINGIFY_(test_suite_name), GTEST_STRINGIFY_(test_name), \
new ::testing::internal::TestMetaFactory<GTEST_TEST_CLASS_NAME_( \
test_suite_name, test_name)>()); \
return 0; \
} \
static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)); \
}; \
int GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)::gtest_registering_dummy_ = \
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::AddToRegistry(); \
void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
// The last argument to INSTANTIATE_TEST_SUITE_P allows the user to specify
// generator and an optional function or functor that generates custom test name
// suffixes based on the test parameters. Such a function or functor should
// accept one argument of type testing::TestParamInfo<class ParamType>, and
// return std::string.
//
// testing::PrintToStringParamName is a builtin test suffix generator that
// returns the value of testing::PrintToString(GetParam()).
//
// Note: test names must be non-empty, unique, and may only contain ASCII
// alphanumeric characters or underscore. Because PrintToString adds quotes
// to std::string and C strings, it won't work for these types.
#define GTEST_EXPAND_(arg) arg
#define GTEST_GET_FIRST_(first, ...) first
#define GTEST_GET_SECOND_(first, second, ...) second
#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \
static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \
"test_suite_name must not be empty"); \
static_assert(sizeof(GTEST_STRINGIFY_(prefix)) > 1, \
"prefix must not be empty"); \
static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \
gtest_##prefix##test_suite_name##_EvalGenerator_() { \
return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \
} \
static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \
const ::testing::TestParamInfo<test_suite_name::ParamType>& info) { \
if (::testing::internal::AlwaysFalse()) { \
::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \
__VA_ARGS__, \
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
DUMMY_PARAM_))); \
auto t = std::make_tuple(__VA_ARGS__); \
static_assert(std::tuple_size<decltype(t)>::value <= 2, \
"Too Many Args!"); \
} \
return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \
__VA_ARGS__, \
::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
DUMMY_PARAM_))))(info); \
} \
static int gtest_##prefix##test_suite_name##_dummy_ \
GTEST_ATTRIBUTE_UNUSED_ = \
::testing::UnitTest::GetInstance() \
->parameterized_test_registry() \
.GetTestSuitePatternHolder<test_suite_name>( \
GTEST_STRINGIFY_(test_suite_name), \
::testing::internal::CodeLocation(__FILE__, __LINE__)) \
->AddTestSuiteInstantiation( \
GTEST_STRINGIFY_(prefix), \
&gtest_##prefix##test_suite_name##_EvalGenerator_, \
&gtest_##prefix##test_suite_name##_EvalGenerateName_, \
__FILE__, __LINE__)
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define INSTANTIATE_TEST_CASE_P \
static_assert(::testing::internal::InstantiateTestCase_P_IsDeprecated(), \
""); \
INSTANTIATE_TEST_SUITE_P
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
-928
View File
@@ -1,928 +0,0 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Google Test - The Google C++ Testing and Mocking Framework
//
// This file implements a universal value printer that can print a
// value of any type T:
//
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
//
// A user can teach this function how to print a class type T by
// defining either operator<<() or PrintTo() in the namespace that
// defines T. More specifically, the FIRST defined function in the
// following list will be used (assuming T is defined in namespace
// foo):
//
// 1. foo::PrintTo(const T&, ostream*)
// 2. operator<<(ostream&, const T&) defined in either foo or the
// global namespace.
//
// However if T is an STL-style container then it is printed element-wise
// unless foo::PrintTo(const T&, ostream*) is defined. Note that
// operator<<() is ignored for container types.
//
// If none of the above is defined, it will print the debug string of
// the value if it is a protocol buffer, or print the raw bytes in the
// value otherwise.
//
// To aid debugging: when T is a reference type, the address of the
// value is also printed; when T is a (const) char pointer, both the
// pointer value and the NUL-terminated string it points to are
// printed.
//
// We also provide some convenient wrappers:
//
// // Prints a value to a string. For a (const or not) char
// // pointer, the NUL-terminated string (but not the pointer) is
// // printed.
// std::string ::testing::PrintToString(const T& value);
//
// // Prints a value tersely: for a reference type, the referenced
// // value (but not the address) is printed; for a (const or not) char
// // pointer, the NUL-terminated string (but not the pointer) is
// // printed.
// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
//
// // Prints value using the type inferred by the compiler. The difference
// // from UniversalTersePrint() is that this function prints both the
// // pointer and the NUL-terminated string for a (const or not) char pointer.
// void ::testing::internal::UniversalPrint(const T& value, ostream*);
//
// // Prints the fields of a tuple tersely to a string vector, one
// // element for each field. Tuple support must be enabled in
// // gtest-port.h.
// std::vector<string> UniversalTersePrintTupleFieldsToStrings(
// const Tuple& value);
//
// Known limitation:
//
// The print primitives print the elements of an STL-style container
// using the compiler-inferred type of *iter where iter is a
// const_iterator of the container. When const_iterator is an input
// iterator but not a forward iterator, this inferred type may not
// match value_type, and the print output may be incorrect. In
// practice, this is rarely a problem as for most containers
// const_iterator is a forward iterator. We'll fix this if there's an
// actual need for it. Note that this fix cannot rely on value_type
// being defined as many user-defined container types don't have
// value_type.
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
#include <functional>
#include <ostream> // NOLINT
#include <sstream>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include "internal/gtest-internal.h"
#include "internal/gtest-port.h"
#if GTEST_HAS_ABSL
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "absl/types/variant.h"
#endif // GTEST_HAS_ABSL
namespace testing {
// Definitions in the 'internal' and 'internal2' name spaces are
// subject to change without notice. DO NOT USE THEM IN USER CODE!
namespace internal2 {
// Prints the given number of bytes in the given object to the given
// ostream.
GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
size_t count,
::std::ostream* os);
// For selecting which printer to use when a given type has neither <<
// nor PrintTo().
enum TypeKind {
kProtobuf, // a protobuf type
kConvertibleToInteger, // a type implicitly convertible to std::intmax_t
// (e.g. a named or unnamed enum type)
#if GTEST_HAS_ABSL
kConvertibleToStringView, // a type implicitly convertible to
// absl::string_view
#endif
kOtherType // anything else
};
// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
// by the universal printer to print a value of type T when neither
// operator<< nor PrintTo() is defined for T, where kTypeKind is the
// "kind" of T as defined by enum TypeKind.
template <typename T, TypeKind kTypeKind>
class TypeWithoutFormatter {
public:
// This default version is called when kTypeKind is kOtherType.
static void PrintValue(const T& value, ::std::ostream* os) {
PrintBytesInObjectTo(
static_cast<const unsigned char*>(
reinterpret_cast<const void*>(std::addressof(value))),
sizeof(value), os);
}
};
// We print a protobuf using its ShortDebugString() when the string
// doesn't exceed this many characters; otherwise we print it using
// DebugString() for better readability.
const size_t kProtobufOneLinerMaxLength = 50;
template <typename T>
class TypeWithoutFormatter<T, kProtobuf> {
public:
static void PrintValue(const T& value, ::std::ostream* os) {
std::string pretty_str = value.ShortDebugString();
if (pretty_str.length() > kProtobufOneLinerMaxLength) {
pretty_str = "\n" + value.DebugString();
}
*os << ("<" + pretty_str + ">");
}
};
template <typename T>
class TypeWithoutFormatter<T, kConvertibleToInteger> {
public:
// Since T has no << operator or PrintTo() but can be implicitly
// converted to the maximum width integer, we print it as a std::intmax_t.
//
// Most likely T is an enum type (either named or unnamed), in which
// case printing it as an integer is the desired behavior. In case
// T is not an enum, printing it as an integer is the best we can do
// given that it has no user-defined printer.
static void PrintValue(const T& value, ::std::ostream* os) {
const std::intmax_t kBigInt = value;
*os << kBigInt;
}
};
#if GTEST_HAS_ABSL
template <typename T>
class TypeWithoutFormatter<T, kConvertibleToStringView> {
public:
// Since T has neither operator<< nor PrintTo() but can be implicitly
// converted to absl::string_view, we print it as a absl::string_view.
//
// Note: the implementation is further below, as it depends on
// internal::PrintTo symbol which is defined later in the file.
static void PrintValue(const T& value, ::std::ostream* os);
};
#endif
// Prints the given value to the given ostream. If the value is a
// protocol message, its debug string is printed; if it's an enum or
// of a type implicitly convertible to std::intmax_t, it's printed as an
// integer; otherwise the bytes in the value are printed. This is
// what UniversalPrinter<T>::Print() does when it knows nothing about
// type T and T has neither << operator nor PrintTo().
//
// A user can override this behavior for a class type Foo by defining
// a << operator in the namespace where Foo is defined.
//
// We put this operator in namespace 'internal2' instead of 'internal'
// to simplify the implementation, as much code in 'internal' needs to
// use << in STL, which would conflict with our own << were it defined
// in 'internal'.
//
// Note that this operator<< takes a generic std::basic_ostream<Char,
// CharTraits> type instead of the more restricted std::ostream. If
// we define it to take an std::ostream instead, we'll get an
// "ambiguous overloads" compiler error when trying to print a type
// Foo that supports streaming to std::basic_ostream<Char,
// CharTraits>, as the compiler cannot tell whether
// operator<<(std::ostream&, const T&) or
// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
// specific.
template <typename Char, typename CharTraits, typename T>
::std::basic_ostream<Char, CharTraits>& operator<<(
::std::basic_ostream<Char, CharTraits>& os, const T& x) {
TypeWithoutFormatter<
T, (internal::IsAProtocolMessage<T>::value
? kProtobuf
: std::is_convertible<const T&, std::intmax_t>::value
? kConvertibleToInteger
:
#if GTEST_HAS_ABSL
std::is_convertible<const T&, absl::string_view>::value
? kConvertibleToStringView
:
#endif
kOtherType)>::PrintValue(x, &os);
return os;
}
} // namespace internal2
} // namespace testing
// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
// magic needed for implementing UniversalPrinter won't work.
namespace testing_internal {
// Used to print a value that is not an STL-style container when the
// user doesn't define PrintTo() for it.
template <typename T>
void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
// With the following statement, during unqualified name lookup,
// testing::internal2::operator<< appears as if it was declared in
// the nearest enclosing namespace that contains both
// ::testing_internal and ::testing::internal2, i.e. the global
// namespace. For more details, refer to the C++ Standard section
// 7.3.4-1 [namespace.udir]. This allows us to fall back onto
// testing::internal2::operator<< in case T doesn't come with a <<
// operator.
//
// We cannot write 'using ::testing::internal2::operator<<;', which
// gcc 3.3 fails to compile due to a compiler bug.
using namespace ::testing::internal2; // NOLINT
// Assuming T is defined in namespace foo, in the next statement,
// the compiler will consider all of:
//
// 1. foo::operator<< (thanks to Koenig look-up),
// 2. ::operator<< (as the current namespace is enclosed in ::),
// 3. testing::internal2::operator<< (thanks to the using statement above).
//
// The operator<< whose type matches T best will be picked.
//
// We deliberately allow #2 to be a candidate, as sometimes it's
// impossible to define #1 (e.g. when foo is ::std, defining
// anything in it is undefined behavior unless you are a compiler
// vendor.).
*os << value;
}
} // namespace testing_internal
namespace testing {
namespace internal {
// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a
// value of type ToPrint that is an operand of a comparison assertion
// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in
// the comparison, and is used to help determine the best way to
// format the value. In particular, when the value is a C string
// (char pointer) and the other operand is an STL string object, we
// want to format the C string as a string, since we know it is
// compared by value with the string object. If the value is a char
// pointer but the other operand is not an STL string object, we don't
// know whether the pointer is supposed to point to a NUL-terminated
// string, and thus want to print it as a pointer to be safe.
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
// The default case.
template <typename ToPrint, typename OtherOperand>
class FormatForComparison {
public:
static ::std::string Format(const ToPrint& value) {
return ::testing::PrintToString(value);
}
};
// Array.
template <typename ToPrint, size_t N, typename OtherOperand>
class FormatForComparison<ToPrint[N], OtherOperand> {
public:
static ::std::string Format(const ToPrint* value) {
return FormatForComparison<const ToPrint*, OtherOperand>::Format(value);
}
};
// By default, print C string as pointers to be safe, as we don't know
// whether they actually point to a NUL-terminated string.
#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType) \
template <typename OtherOperand> \
class FormatForComparison<CharType*, OtherOperand> { \
public: \
static ::std::string Format(CharType* value) { \
return ::testing::PrintToString(static_cast<const void*>(value)); \
} \
}
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char);
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_
// If a C string is compared with an STL string object, we know it's meant
// to point to a NUL-terminated string, and thus can print it as a string.
#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
template <> \
class FormatForComparison<CharType*, OtherStringType> { \
public: \
static ::std::string Format(CharType* value) { \
return ::testing::PrintToString(value); \
} \
}
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
#if GTEST_HAS_STD_WSTRING
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
#endif
#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_
// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
// operand to be used in a failure message. The type (but not value)
// of the other operand may affect the format. This allows us to
// print a char* as a raw pointer when it is compared against another
// char* or void*, and print it as a C string when it is compared
// against an std::string object, for example.
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
template <typename T1, typename T2>
std::string FormatForComparisonFailureMessage(
const T1& value, const T2& /* other_operand */) {
return FormatForComparison<T1, T2>::Format(value);
}
// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
// value to the given ostream. The caller must ensure that
// 'ostream_ptr' is not NULL, or the behavior is undefined.
//
// We define UniversalPrinter as a class template (as opposed to a
// function template), as we need to partially specialize it for
// reference types, which cannot be done with function templates.
template <typename T>
class UniversalPrinter;
template <typename T>
void UniversalPrint(const T& value, ::std::ostream* os);
enum DefaultPrinterType {
kPrintContainer,
kPrintPointer,
kPrintFunctionPointer,
kPrintOther,
};
template <DefaultPrinterType type> struct WrapPrinterType {};
// Used to print an STL-style container when the user doesn't define
// a PrintTo() for it.
template <typename C>
void DefaultPrintTo(WrapPrinterType<kPrintContainer> /* dummy */,
const C& container, ::std::ostream* os) {
const size_t kMaxCount = 32; // The maximum number of elements to print.
*os << '{';
size_t count = 0;
for (typename C::const_iterator it = container.begin();
it != container.end(); ++it, ++count) {
if (count > 0) {
*os << ',';
if (count == kMaxCount) { // Enough has been printed.
*os << " ...";
break;
}
}
*os << ' ';
// We cannot call PrintTo(*it, os) here as PrintTo() doesn't
// handle *it being a native array.
internal::UniversalPrint(*it, os);
}
if (count > 0) {
*os << ' ';
}
*os << '}';
}
// Used to print a pointer that is neither a char pointer nor a member
// pointer, when the user doesn't define PrintTo() for it. (A member
// variable pointer or member function pointer doesn't really point to
// a location in the address space. Their representation is
// implementation-defined. Therefore they will be printed as raw
// bytes.)
template <typename T>
void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */,
T* p, ::std::ostream* os) {
if (p == nullptr) {
*os << "NULL";
} else {
// T is not a function type. We just call << to print p,
// relying on ADL to pick up user-defined << for their pointer
// types, if any.
*os << p;
}
}
template <typename T>
void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */,
T* p, ::std::ostream* os) {
if (p == nullptr) {
*os << "NULL";
} else {
// T is a function type, so '*os << p' doesn't do what we want
// (it just prints p as bool). We want to print p as a const
// void*.
*os << reinterpret_cast<const void*>(p);
}
}
// Used to print a non-container, non-pointer value when the user
// doesn't define PrintTo() for it.
template <typename T>
void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */,
const T& value, ::std::ostream* os) {
::testing_internal::DefaultPrintNonContainerTo(value, os);
}
// Prints the given value using the << operator if it has one;
// otherwise prints the bytes in it. This is what
// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
// or overloaded for type T.
//
// A user can override this behavior for a class type Foo by defining
// an overload of PrintTo() in the namespace where Foo is defined. We
// give the user this option as sometimes defining a << operator for
// Foo is not desirable (e.g. the coding style may prevent doing it,
// or there is already a << operator but it doesn't do what the user
// wants).
template <typename T>
void PrintTo(const T& value, ::std::ostream* os) {
// DefaultPrintTo() is overloaded. The type of its first argument
// determines which version will be picked.
//
// Note that we check for container types here, prior to we check
// for protocol message types in our operator<<. The rationale is:
//
// For protocol messages, we want to give people a chance to
// override Google Mock's format by defining a PrintTo() or
// operator<<. For STL containers, other formats can be
// incompatible with Google Mock's format for the container
// elements; therefore we check for container types here to ensure
// that our format is used.
//
// Note that MSVC and clang-cl do allow an implicit conversion from
// pointer-to-function to pointer-to-object, but clang-cl warns on it.
// So don't use ImplicitlyConvertible if it can be helped since it will
// cause this warning, and use a separate overload of DefaultPrintTo for
// function pointers so that the `*os << p` in the object pointer overload
// doesn't cause that warning either.
DefaultPrintTo(
WrapPrinterType <
(sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
!IsRecursiveContainer<T>::value
? kPrintContainer
: !std::is_pointer<T>::value
? kPrintOther
: std::is_function<typename std::remove_pointer<T>::type>::value
? kPrintFunctionPointer
: kPrintPointer > (),
value, os);
}
// The following list of PrintTo() overloads tells
// UniversalPrinter<T>::Print() how to print standard types (built-in
// types, strings, plain arrays, and pointers).
// Overloads for various char types.
GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
inline void PrintTo(char c, ::std::ostream* os) {
// When printing a plain char, we always treat it as unsigned. This
// way, the output won't be affected by whether the compiler thinks
// char is signed or not.
PrintTo(static_cast<unsigned char>(c), os);
}
// Overloads for other simple built-in types.
inline void PrintTo(bool x, ::std::ostream* os) {
*os << (x ? "true" : "false");
}
// Overload for wchar_t type.
// Prints a wchar_t as a symbol if it is printable or as its internal
// code otherwise and also as its decimal code (except for L'\0').
// The L'\0' char is printed as "L'\\0'". The decimal code is printed
// as signed integer when wchar_t is implemented by the compiler
// as a signed type and is printed as an unsigned integer when wchar_t
// is implemented as an unsigned type.
GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
// Overloads for C strings.
GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
inline void PrintTo(char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const char*>(s), os);
}
// signed/unsigned char is often used for representing binary data, so
// we print pointers to it as void* to be safe.
inline void PrintTo(const signed char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
inline void PrintTo(signed char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
inline void PrintTo(unsigned char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
// MSVC can be configured to define wchar_t as a typedef of unsigned
// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
// type. When wchar_t is a typedef, defining an overload for const
// wchar_t* would cause unsigned short* be printed as a wide string,
// possibly causing invalid memory accesses.
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
// Overloads for wide C strings
GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
inline void PrintTo(wchar_t* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const wchar_t*>(s), os);
}
#endif
// Overload for C arrays. Multi-dimensional arrays are printed
// properly.
// Prints the given number of elements in an array, without printing
// the curly braces.
template <typename T>
void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
UniversalPrint(a[0], os);
for (size_t i = 1; i != count; i++) {
*os << ", ";
UniversalPrint(a[i], os);
}
}
// Overloads for ::std::string.
GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
PrintStringTo(s, os);
}
// Overloads for ::std::wstring.
#if GTEST_HAS_STD_WSTRING
GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
PrintWideStringTo(s, os);
}
#endif // GTEST_HAS_STD_WSTRING
#if GTEST_HAS_ABSL
// Overload for absl::string_view.
inline void PrintTo(absl::string_view sp, ::std::ostream* os) {
PrintTo(::std::string(sp), os);
}
#endif // GTEST_HAS_ABSL
inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
template <typename T>
void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) {
UniversalPrinter<T&>::Print(ref.get(), os);
}
// Helper function for printing a tuple. T must be instantiated with
// a tuple type.
template <typename T>
void PrintTupleTo(const T&, std::integral_constant<size_t, 0>,
::std::ostream*) {}
template <typename T, size_t I>
void PrintTupleTo(const T& t, std::integral_constant<size_t, I>,
::std::ostream* os) {
PrintTupleTo(t, std::integral_constant<size_t, I - 1>(), os);
GTEST_INTENTIONAL_CONST_COND_PUSH_()
if (I > 1) {
GTEST_INTENTIONAL_CONST_COND_POP_()
*os << ", ";
}
UniversalPrinter<typename std::tuple_element<I - 1, T>::type>::Print(
std::get<I - 1>(t), os);
}
template <typename... Types>
void PrintTo(const ::std::tuple<Types...>& t, ::std::ostream* os) {
*os << "(";
PrintTupleTo(t, std::integral_constant<size_t, sizeof...(Types)>(), os);
*os << ")";
}
// Overload for std::pair.
template <typename T1, typename T2>
void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
*os << '(';
// We cannot use UniversalPrint(value.first, os) here, as T1 may be
// a reference type. The same for printing value.second.
UniversalPrinter<T1>::Print(value.first, os);
*os << ", ";
UniversalPrinter<T2>::Print(value.second, os);
*os << ')';
}
// Implements printing a non-reference type T by letting the compiler
// pick the right overload of PrintTo() for T.
template <typename T>
class UniversalPrinter {
public:
// MSVC warns about adding const to a function type, so we want to
// disable the warning.
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
// Note: we deliberately don't call this PrintTo(), as that name
// conflicts with ::testing::internal::PrintTo in the body of the
// function.
static void Print(const T& value, ::std::ostream* os) {
// By default, ::testing::internal::PrintTo() is used for printing
// the value.
//
// Thanks to Koenig look-up, if T is a class and has its own
// PrintTo() function defined in its namespace, that function will
// be visible here. Since it is more specific than the generic ones
// in ::testing::internal, it will be picked by the compiler in the
// following statement - exactly what we want.
PrintTo(value, os);
}
GTEST_DISABLE_MSC_WARNINGS_POP_()
};
#if GTEST_HAS_ABSL
// Printer for absl::optional
template <typename T>
class UniversalPrinter<::absl::optional<T>> {
public:
static void Print(const ::absl::optional<T>& value, ::std::ostream* os) {
*os << '(';
if (!value) {
*os << "nullopt";
} else {
UniversalPrint(*value, os);
}
*os << ')';
}
};
// Printer for absl::variant
template <typename... T>
class UniversalPrinter<::absl::variant<T...>> {
public:
static void Print(const ::absl::variant<T...>& value, ::std::ostream* os) {
*os << '(';
absl::visit(Visitor{os}, value);
*os << ')';
}
private:
struct Visitor {
template <typename U>
void operator()(const U& u) const {
*os << "'" << GetTypeName<U>() << "' with value ";
UniversalPrint(u, os);
}
::std::ostream* os;
};
};
#endif // GTEST_HAS_ABSL
// UniversalPrintArray(begin, len, os) prints an array of 'len'
// elements, starting at address 'begin'.
template <typename T>
void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
if (len == 0) {
*os << "{}";
} else {
*os << "{ ";
const size_t kThreshold = 18;
const size_t kChunkSize = 8;
// If the array has more than kThreshold elements, we'll have to
// omit some details by printing only the first and the last
// kChunkSize elements.
if (len <= kThreshold) {
PrintRawArrayTo(begin, len, os);
} else {
PrintRawArrayTo(begin, kChunkSize, os);
*os << ", ..., ";
PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
}
*os << " }";
}
}
// This overload prints a (const) char array compactly.
GTEST_API_ void UniversalPrintArray(
const char* begin, size_t len, ::std::ostream* os);
// This overload prints a (const) wchar_t array compactly.
GTEST_API_ void UniversalPrintArray(
const wchar_t* begin, size_t len, ::std::ostream* os);
// Implements printing an array type T[N].
template <typename T, size_t N>
class UniversalPrinter<T[N]> {
public:
// Prints the given array, omitting some elements when there are too
// many.
static void Print(const T (&a)[N], ::std::ostream* os) {
UniversalPrintArray(a, N, os);
}
};
// Implements printing a reference type T&.
template <typename T>
class UniversalPrinter<T&> {
public:
// MSVC warns about adding const to a function type, so we want to
// disable the warning.
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
static void Print(const T& value, ::std::ostream* os) {
// Prints the address of the value. We use reinterpret_cast here
// as static_cast doesn't compile when T is a function type.
*os << "@" << reinterpret_cast<const void*>(&value) << " ";
// Then prints the value itself.
UniversalPrint(value, os);
}
GTEST_DISABLE_MSC_WARNINGS_POP_()
};
// Prints a value tersely: for a reference type, the referenced value
// (but not the address) is printed; for a (const) char pointer, the
// NUL-terminated string (but not the pointer) is printed.
template <typename T>
class UniversalTersePrinter {
public:
static void Print(const T& value, ::std::ostream* os) {
UniversalPrint(value, os);
}
};
template <typename T>
class UniversalTersePrinter<T&> {
public:
static void Print(const T& value, ::std::ostream* os) {
UniversalPrint(value, os);
}
};
template <typename T, size_t N>
class UniversalTersePrinter<T[N]> {
public:
static void Print(const T (&value)[N], ::std::ostream* os) {
UniversalPrinter<T[N]>::Print(value, os);
}
};
template <>
class UniversalTersePrinter<const char*> {
public:
static void Print(const char* str, ::std::ostream* os) {
if (str == nullptr) {
*os << "NULL";
} else {
UniversalPrint(std::string(str), os);
}
}
};
template <>
class UniversalTersePrinter<char*> {
public:
static void Print(char* str, ::std::ostream* os) {
UniversalTersePrinter<const char*>::Print(str, os);
}
};
#if GTEST_HAS_STD_WSTRING
template <>
class UniversalTersePrinter<const wchar_t*> {
public:
static void Print(const wchar_t* str, ::std::ostream* os) {
if (str == nullptr) {
*os << "NULL";
} else {
UniversalPrint(::std::wstring(str), os);
}
}
};
#endif
template <>
class UniversalTersePrinter<wchar_t*> {
public:
static void Print(wchar_t* str, ::std::ostream* os) {
UniversalTersePrinter<const wchar_t*>::Print(str, os);
}
};
template <typename T>
void UniversalTersePrint(const T& value, ::std::ostream* os) {
UniversalTersePrinter<T>::Print(value, os);
}
// Prints a value using the type inferred by the compiler. The
// difference between this and UniversalTersePrint() is that for a
// (const) char pointer, this prints both the pointer and the
// NUL-terminated string.
template <typename T>
void UniversalPrint(const T& value, ::std::ostream* os) {
// A workarond for the bug in VC++ 7.1 that prevents us from instantiating
// UniversalPrinter with T directly.
typedef T T1;
UniversalPrinter<T1>::Print(value, os);
}
typedef ::std::vector< ::std::string> Strings;
// Tersely prints the first N fields of a tuple to a string vector,
// one element for each field.
template <typename Tuple>
void TersePrintPrefixToStrings(const Tuple&, std::integral_constant<size_t, 0>,
Strings*) {}
template <typename Tuple, size_t I>
void TersePrintPrefixToStrings(const Tuple& t,
std::integral_constant<size_t, I>,
Strings* strings) {
TersePrintPrefixToStrings(t, std::integral_constant<size_t, I - 1>(),
strings);
::std::stringstream ss;
UniversalTersePrint(std::get<I - 1>(t), &ss);
strings->push_back(ss.str());
}
// Prints the fields of a tuple tersely to a string vector, one
// element for each field. See the comment before
// UniversalTersePrint() for how we define "tersely".
template <typename Tuple>
Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
Strings result;
TersePrintPrefixToStrings(
value, std::integral_constant<size_t, std::tuple_size<Tuple>::value>(),
&result);
return result;
}
} // namespace internal
#if GTEST_HAS_ABSL
namespace internal2 {
template <typename T>
void TypeWithoutFormatter<T, kConvertibleToStringView>::PrintValue(
const T& value, ::std::ostream* os) {
internal::PrintTo(absl::string_view(value), os);
}
} // namespace internal2
#endif
template <typename T>
::std::string PrintToString(const T& value) {
::std::stringstream ss;
internal::UniversalTersePrinter<T>::Print(value, &ss);
return ss.str();
}
} // namespace testing
// Include any custom printer added by the local installation.
// We must include this header at the end to make sure it can use the
// declarations from this file.
#include "internal/custom/gtest-printers.h"
#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
-238
View File
@@ -1,238 +0,0 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Utilities for testing Google Test itself and code that uses Google Test
// (e.g. frameworks built on top of Google Test).
// GOOGLETEST_CM0004 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
#include "gtest.h"
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
/* class A needs to have dll-interface to be used by clients of class B */)
namespace testing {
// This helper class can be used to mock out Google Test failure reporting
// so that we can test Google Test or code that builds on Google Test.
//
// An object of this class appends a TestPartResult object to the
// TestPartResultArray object given in the constructor whenever a Google Test
// failure is reported. It can either intercept only failures that are
// generated in the same thread that created this object or it can intercept
// all generated failures. The scope of this mock object can be controlled with
// the second argument to the two arguments constructor.
class GTEST_API_ ScopedFakeTestPartResultReporter
: public TestPartResultReporterInterface {
public:
// The two possible mocking modes of this object.
enum InterceptMode {
INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures.
INTERCEPT_ALL_THREADS // Intercepts all failures.
};
// The c'tor sets this object as the test part result reporter used
// by Google Test. The 'result' parameter specifies where to report the
// results. This reporter will only catch failures generated in the current
// thread. DEPRECATED
explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
// Same as above, but you can choose the interception scope of this object.
ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
TestPartResultArray* result);
// The d'tor restores the previous test part result reporter.
~ScopedFakeTestPartResultReporter() override;
// Appends the TestPartResult object to the TestPartResultArray
// received in the constructor.
//
// This method is from the TestPartResultReporterInterface
// interface.
void ReportTestPartResult(const TestPartResult& result) override;
private:
void Init();
const InterceptMode intercept_mode_;
TestPartResultReporterInterface* old_reporter_;
TestPartResultArray* const result_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
};
namespace internal {
// A helper class for implementing EXPECT_FATAL_FAILURE() and
// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given
// TestPartResultArray contains exactly one failure that has the given
// type and contains the given substring. If that's not the case, a
// non-fatal failure will be generated.
class GTEST_API_ SingleFailureChecker {
public:
// The constructor remembers the arguments.
SingleFailureChecker(const TestPartResultArray* results,
TestPartResult::Type type, const std::string& substr);
~SingleFailureChecker();
private:
const TestPartResultArray* const results_;
const TestPartResult::Type type_;
const std::string substr_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
};
} // namespace internal
} // namespace testing
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
// A set of macros for testing Google Test assertions or code that's expected
// to generate Google Test fatal failures. It verifies that the given
// statement will cause exactly one fatal Google Test failure with 'substr'
// being part of the failure message.
//
// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
// affects and considers failures generated in the current thread and
// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
//
// The verification of the assertion is done correctly even when the statement
// throws an exception or aborts the current function.
//
// Known restrictions:
// - 'statement' cannot reference local non-static variables or
// non-static members of the current object.
// - 'statement' cannot return a value.
// - You cannot stream a failure message to this macro.
//
// Note that even though the implementations of the following two
// macros are much alike, we cannot refactor them to use a common
// helper macro, due to some peculiarity in how the preprocessor
// works. The AcceptsMacroThatExpandsToUnprotectedComma test in
// gtest_unittest.cc will fail to compile if we do that.
#define EXPECT_FATAL_FAILURE(statement, substr) \
do { \
class GTestExpectFatalFailureHelper {\
public:\
static void Execute() { statement; }\
};\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
GTestExpectFatalFailureHelper::Execute();\
}\
} while (::testing::internal::AlwaysFalse())
#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
do { \
class GTestExpectFatalFailureHelper {\
public:\
static void Execute() { statement; }\
};\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ALL_THREADS, &gtest_failures);\
GTestExpectFatalFailureHelper::Execute();\
}\
} while (::testing::internal::AlwaysFalse())
// A macro for testing Google Test assertions or code that's expected to
// generate Google Test non-fatal failures. It asserts that the given
// statement will cause exactly one non-fatal Google Test failure with 'substr'
// being part of the failure message.
//
// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
// affects and considers failures generated in the current thread and
// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
//
// 'statement' is allowed to reference local variables and members of
// the current object.
//
// The verification of the assertion is done correctly even when the statement
// throws an exception or aborts the current function.
//
// Known restrictions:
// - You cannot stream a failure message to this macro.
//
// Note that even though the implementations of the following two
// macros are much alike, we cannot refactor them to use a common
// helper macro, due to some peculiarity in how the preprocessor
// works. If we do that, the code won't compile when the user gives
// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
// expands to code containing an unprotected comma. The
// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
// catches that.
//
// For the same reason, we have to write
// if (::testing::internal::AlwaysTrue()) { statement; }
// instead of
// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
// to avoid an MSVC warning on unreachable code.
#define EXPECT_NONFATAL_FAILURE(statement, substr) \
do {\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
(substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter:: \
INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
if (::testing::internal::AlwaysTrue()) { statement; }\
}\
} while (::testing::internal::AlwaysFalse())
#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
do {\
::testing::TestPartResultArray gtest_failures;\
::testing::internal::SingleFailureChecker gtest_checker(\
&gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
(substr));\
{\
::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
&gtest_failures);\
if (::testing::internal::AlwaysTrue()) { statement; }\
}\
} while (::testing::internal::AlwaysFalse())
#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
-185
View File
@@ -1,185 +0,0 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
#include <iosfwd>
#include <vector>
#include "internal/gtest-internal.h"
#include "internal/gtest-string.h"
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
/* class A needs to have dll-interface to be used by clients of class B */)
namespace testing {
// A copyable object representing the result of a test part (i.e. an
// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
//
// Don't inherit from TestPartResult as its destructor is not virtual.
class GTEST_API_ TestPartResult {
public:
// The possible outcomes of a test part (i.e. an assertion or an
// explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
enum Type {
kSuccess, // Succeeded.
kNonFatalFailure, // Failed but the test can continue.
kFatalFailure, // Failed and the test should be terminated.
kSkip // Skipped.
};
// C'tor. TestPartResult does NOT have a default constructor.
// Always use this constructor (with parameters) to create a
// TestPartResult object.
TestPartResult(Type a_type, const char* a_file_name, int a_line_number,
const char* a_message)
: type_(a_type),
file_name_(a_file_name == nullptr ? "" : a_file_name),
line_number_(a_line_number),
summary_(ExtractSummary(a_message)),
message_(a_message) {}
// Gets the outcome of the test part.
Type type() const { return type_; }
// Gets the name of the source file where the test part took place, or
// NULL if it's unknown.
const char* file_name() const {
return file_name_.empty() ? nullptr : file_name_.c_str();
}
// Gets the line in the source file where the test part took place,
// or -1 if it's unknown.
int line_number() const { return line_number_; }
// Gets the summary of the failure message.
const char* summary() const { return summary_.c_str(); }
// Gets the message associated with the test part.
const char* message() const { return message_.c_str(); }
// Returns true if and only if the test part was skipped.
bool skipped() const { return type_ == kSkip; }
// Returns true if and only if the test part passed.
bool passed() const { return type_ == kSuccess; }
// Returns true if and only if the test part non-fatally failed.
bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
// Returns true if and only if the test part fatally failed.
bool fatally_failed() const { return type_ == kFatalFailure; }
// Returns true if and only if the test part failed.
bool failed() const { return fatally_failed() || nonfatally_failed(); }
private:
Type type_;
// Gets the summary of the failure message by omitting the stack
// trace in it.
static std::string ExtractSummary(const char* message);
// The name of the source file where the test part took place, or
// "" if the source file is unknown.
std::string file_name_;
// The line in the source file where the test part took place, or -1
// if the line number is unknown.
int line_number_;
std::string summary_; // The test failure summary.
std::string message_; // The test failure message.
};
// Prints a TestPartResult object.
std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
// An array of TestPartResult objects.
//
// Don't inherit from TestPartResultArray as its destructor is not
// virtual.
class GTEST_API_ TestPartResultArray {
public:
TestPartResultArray() {}
// Appends the given TestPartResult to the array.
void Append(const TestPartResult& result);
// Returns the TestPartResult at the given index (0-based).
const TestPartResult& GetTestPartResult(int index) const;
// Returns the number of TestPartResult objects in the array.
int size() const;
private:
std::vector<TestPartResult> array_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
};
// This interface knows how to report a test part result.
class GTEST_API_ TestPartResultReporterInterface {
public:
virtual ~TestPartResultReporterInterface() {}
virtual void ReportTestPartResult(const TestPartResult& result) = 0;
};
namespace internal {
// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
// statement generates new fatal failures. To do so it registers itself as the
// current test part result reporter. Besides checking if fatal failures were
// reported, it only delegates the reporting to the former result reporter.
// The original result reporter is restored in the destructor.
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
class GTEST_API_ HasNewFatalFailureHelper
: public TestPartResultReporterInterface {
public:
HasNewFatalFailureHelper();
~HasNewFatalFailureHelper() override;
void ReportTestPartResult(const TestPartResult& result) override;
bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
private:
bool has_new_fatal_failure_;
TestPartResultReporterInterface* original_reporter_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
};
} // namespace internal
} // namespace testing
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
-328
View File
@@ -1,328 +0,0 @@
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
// This header implements typed tests and type-parameterized tests.
// Typed (aka type-driven) tests repeat the same test for types in a
// list. You must know which types you want to test with when writing
// typed tests. Here's how you do it:
#if 0
// First, define a fixture class template. It should be parameterized
// by a type. Remember to derive it from testing::Test.
template <typename T>
class FooTest : public testing::Test {
public:
...
typedef std::list<T> List;
static T shared_;
T value_;
};
// Next, associate a list of types with the test suite, which will be
// repeated for each type in the list. The typedef is necessary for
// the macro to parse correctly.
typedef testing::Types<char, int, unsigned int> MyTypes;
TYPED_TEST_SUITE(FooTest, MyTypes);
// If the type list contains only one type, you can write that type
// directly without Types<...>:
// TYPED_TEST_SUITE(FooTest, int);
// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
// tests for this test suite as you want.
TYPED_TEST(FooTest, DoesBlah) {
// Inside a test, refer to the special name TypeParam to get the type
// parameter. Since we are inside a derived class template, C++ requires
// us to visit the members of FooTest via 'this'.
TypeParam n = this->value_;
// To visit static members of the fixture, add the TestFixture::
// prefix.
n += TestFixture::shared_;
// To refer to typedefs in the fixture, add the "typename
// TestFixture::" prefix.
typename TestFixture::List values;
values.push_back(n);
...
}
TYPED_TEST(FooTest, HasPropertyA) { ... }
// TYPED_TEST_SUITE takes an optional third argument which allows to specify a
// class that generates custom test name suffixes based on the type. This should
// be a class which has a static template function GetName(int index) returning
// a string for each type. The provided integer index equals the index of the
// type in the provided type list. In many cases the index can be ignored.
//
// For example:
// class MyTypeNames {
// public:
// template <typename T>
// static std::string GetName(int) {
// if (std::is_same<T, char>()) return "char";
// if (std::is_same<T, int>()) return "int";
// if (std::is_same<T, unsigned int>()) return "unsignedInt";
// }
// };
// TYPED_TEST_SUITE(FooTest, MyTypes, MyTypeNames);
#endif // 0
// Type-parameterized tests are abstract test patterns parameterized
// by a type. Compared with typed tests, type-parameterized tests
// allow you to define the test pattern without knowing what the type
// parameters are. The defined pattern can be instantiated with
// different types any number of times, in any number of translation
// units.
//
// If you are designing an interface or concept, you can define a
// suite of type-parameterized tests to verify properties that any
// valid implementation of the interface/concept should have. Then,
// each implementation can easily instantiate the test suite to verify
// that it conforms to the requirements, without having to write
// similar tests repeatedly. Here's an example:
#if 0
// First, define a fixture class template. It should be parameterized
// by a type. Remember to derive it from testing::Test.
template <typename T>
class FooTest : public testing::Test {
...
};
// Next, declare that you will define a type-parameterized test suite
// (the _P suffix is for "parameterized" or "pattern", whichever you
// prefer):
TYPED_TEST_SUITE_P(FooTest);
// Then, use TYPED_TEST_P() to define as many type-parameterized tests
// for this type-parameterized test suite as you want.
TYPED_TEST_P(FooTest, DoesBlah) {
// Inside a test, refer to TypeParam to get the type parameter.
TypeParam n = 0;
...
}
TYPED_TEST_P(FooTest, HasPropertyA) { ... }
// Now the tricky part: you need to register all test patterns before
// you can instantiate them. The first argument of the macro is the
// test suite name; the rest are the names of the tests in this test
// case.
REGISTER_TYPED_TEST_SUITE_P(FooTest,
DoesBlah, HasPropertyA);
// Finally, you are free to instantiate the pattern with the types you
// want. If you put the above code in a header file, you can #include
// it in multiple C++ source files and instantiate it multiple times.
//
// To distinguish different instances of the pattern, the first
// argument to the INSTANTIATE_* macro is a prefix that will be added
// to the actual test suite name. Remember to pick unique prefixes for
// different instances.
typedef testing::Types<char, int, unsigned int> MyTypes;
INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
// If the type list contains only one type, you can write that type
// directly without Types<...>:
// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int);
//
// Similar to the optional argument of TYPED_TEST_SUITE above,
// INSTANTIATE_TEST_SUITE_P takes an optional fourth argument which allows to
// generate custom names.
// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes, MyTypeNames);
#endif // 0
#include "internal/gtest-port.h"
#include "internal/gtest-type-util.h"
// Implements typed tests.
#if GTEST_HAS_TYPED_TEST
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Expands to the name of the typedef for the type parameters of the
// given test suite.
#define GTEST_TYPE_PARAMS_(TestSuiteName) gtest_type_params_##TestSuiteName##_
// Expands to the name of the typedef for the NameGenerator, responsible for
// creating the suffixes of the name.
#define GTEST_NAME_GENERATOR_(TestSuiteName) \
gtest_type_params_##TestSuiteName##_NameGenerator
#define TYPED_TEST_SUITE(CaseName, Types, ...) \
typedef ::testing::internal::GenerateTypeList<Types>::type \
GTEST_TYPE_PARAMS_(CaseName); \
typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
GTEST_NAME_GENERATOR_(CaseName)
#define TYPED_TEST(CaseName, TestName) \
template <typename gtest_TypeParam_> \
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
: public CaseName<gtest_TypeParam_> { \
private: \
typedef CaseName<gtest_TypeParam_> TestFixture; \
typedef gtest_TypeParam_ TypeParam; \
void TestBody() override; \
}; \
static bool gtest_##CaseName##_##TestName##_registered_ \
GTEST_ATTRIBUTE_UNUSED_ = ::testing::internal::TypeParameterizedTest< \
CaseName, \
::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName, \
TestName)>, \
GTEST_TYPE_PARAMS_( \
CaseName)>::Register("", \
::testing::internal::CodeLocation( \
__FILE__, __LINE__), \
#CaseName, #TestName, 0, \
::testing::internal::GenerateNames< \
GTEST_NAME_GENERATOR_(CaseName), \
GTEST_TYPE_PARAMS_(CaseName)>()); \
template <typename gtest_TypeParam_> \
void GTEST_TEST_CLASS_NAME_(CaseName, \
TestName)<gtest_TypeParam_>::TestBody()
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define TYPED_TEST_CASE \
static_assert(::testing::internal::TypedTestCaseIsDeprecated(), ""); \
TYPED_TEST_SUITE
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#endif // GTEST_HAS_TYPED_TEST
// Implements type-parameterized tests.
#if GTEST_HAS_TYPED_TEST_P
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Expands to the namespace name that the type-parameterized tests for
// the given type-parameterized test suite are defined in. The exact
// name of the namespace is subject to change without notice.
#define GTEST_SUITE_NAMESPACE_(TestSuiteName) gtest_suite_##TestSuiteName##_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Expands to the name of the variable used to remember the names of
// the defined tests in the given test suite.
#define GTEST_TYPED_TEST_SUITE_P_STATE_(TestSuiteName) \
gtest_typed_test_suite_p_state_##TestSuiteName##_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
//
// Expands to the name of the variable used to remember the names of
// the registered tests in the given test suite.
#define GTEST_REGISTERED_TEST_NAMES_(TestSuiteName) \
gtest_registered_test_names_##TestSuiteName##_
// The variables defined in the type-parameterized test macros are
// static as typically these macros are used in a .h file that can be
// #included in multiple translation units linked together.
#define TYPED_TEST_SUITE_P(SuiteName) \
static ::testing::internal::TypedTestSuitePState \
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName)
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define TYPED_TEST_CASE_P \
static_assert(::testing::internal::TypedTestCase_P_IsDeprecated(), ""); \
TYPED_TEST_SUITE_P
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define TYPED_TEST_P(SuiteName, TestName) \
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
template <typename gtest_TypeParam_> \
class TestName : public SuiteName<gtest_TypeParam_> { \
private: \
typedef SuiteName<gtest_TypeParam_> TestFixture; \
typedef gtest_TypeParam_ TypeParam; \
void TestBody() override; \
}; \
static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
__FILE__, __LINE__, #SuiteName, #TestName); \
} \
template <typename gtest_TypeParam_> \
void GTEST_SUITE_NAMESPACE_( \
SuiteName)::TestName<gtest_TypeParam_>::TestBody()
#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \
namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \
} \
static const char* const GTEST_REGISTERED_TEST_NAMES_( \
SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \
GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
__FILE__, __LINE__, #__VA_ARGS__)
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define REGISTER_TYPED_TEST_CASE_P \
static_assert(::testing::internal::RegisterTypedTestCase_P_IsDeprecated(), \
""); \
REGISTER_TYPED_TEST_SUITE_P
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \
::testing::internal::TypeParameterizedTestSuite< \
SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
::testing::internal::GenerateTypeList<Types>::type>:: \
Register(#Prefix, \
::testing::internal::CodeLocation(__FILE__, __LINE__), \
&GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName), #SuiteName, \
GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
::testing::internal::GenerateNames< \
::testing::internal::NameGeneratorSelector< \
__VA_ARGS__>::type, \
::testing::internal::GenerateTypeList<Types>::type>())
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define INSTANTIATE_TYPED_TEST_CASE_P \
static_assert( \
::testing::internal::InstantiateTypedTestCase_P_IsDeprecated(), ""); \
INSTANTIATE_TYPED_TEST_SUITE_P
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#endif // GTEST_HAS_TYPED_TEST_P
#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
File diff suppressed because it is too large. Load diff
-359
View File
@@ -1,359 +0,0 @@
// Copyright 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file is AUTOMATICALLY GENERATED on 01/02/2019 by command
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
//
// Implements a family of generic predicate assertion macros.
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
#include "gtest.h"
namespace testing {
// This header implements a family of generic predicate assertion
// macros:
//
// ASSERT_PRED_FORMAT1(pred_format, v1)
// ASSERT_PRED_FORMAT2(pred_format, v1, v2)
// ...
//
// where pred_format is a function or functor that takes n (in the
// case of ASSERT_PRED_FORMATn) values and their source expression
// text, and returns a testing::AssertionResult. See the definition
// of ASSERT_EQ in gtest.h for an example.
//
// If you don't care about formatting, you can use the more
// restrictive version:
//
// ASSERT_PRED1(pred, v1)
// ASSERT_PRED2(pred, v1, v2)
// ...
//
// where pred is an n-ary function or functor that returns bool,
// and the values v1, v2, ..., must support the << operator for
// streaming to std::ostream.
//
// We also define the EXPECT_* variations.
//
// For now we only support predicates whose arity is at most 5.
// Please email [email protected] if you need
// support for higher arities.
// GTEST_ASSERT_ is the basic statement to which all of the assertions
// in this file reduce. Don't use this in your code.
#define GTEST_ASSERT_(expression, on_failure) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (const ::testing::AssertionResult gtest_ar = (expression)) \
; \
else \
on_failure(gtest_ar.failure_message())
// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
// this in your code.
template <typename Pred,
typename T1>
AssertionResult AssertPred1Helper(const char* pred_text,
const char* e1,
Pred pred,
const T1& v1) {
if (pred(v1)) return AssertionSuccess();
return AssertionFailure()
<< pred_text << "(" << e1 << ") evaluates to false, where"
<< "\n"
<< e1 << " evaluates to " << ::testing::PrintToString(v1);
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
// Don't use this in your code.
#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
GTEST_ASSERT_(pred_format(#v1, v1), \
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
// this in your code.
#define GTEST_PRED1_(pred, v1, on_failure)\
GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
#v1, \
pred, \
v1), on_failure)
// Unary predicate assertion macros.
#define EXPECT_PRED_FORMAT1(pred_format, v1) \
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED1(pred, v1) \
GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT1(pred_format, v1) \
GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED1(pred, v1) \
GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
// this in your code.
template <typename Pred,
typename T1,
typename T2>
AssertionResult AssertPred2Helper(const char* pred_text,
const char* e1,
const char* e2,
Pred pred,
const T1& v1,
const T2& v2) {
if (pred(v1, v2)) return AssertionSuccess();
return AssertionFailure()
<< pred_text << "(" << e1 << ", " << e2
<< ") evaluates to false, where"
<< "\n"
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
<< e2 << " evaluates to " << ::testing::PrintToString(v2);
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
// Don't use this in your code.
#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
// this in your code.
#define GTEST_PRED2_(pred, v1, v2, on_failure)\
GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
#v1, \
#v2, \
pred, \
v1, \
v2), on_failure)
// Binary predicate assertion macros.
#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED2(pred, v1, v2) \
GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED2(pred, v1, v2) \
GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
// this in your code.
template <typename Pred,
typename T1,
typename T2,
typename T3>
AssertionResult AssertPred3Helper(const char* pred_text,
const char* e1,
const char* e2,
const char* e3,
Pred pred,
const T1& v1,
const T2& v2,
const T3& v3) {
if (pred(v1, v2, v3)) return AssertionSuccess();
return AssertionFailure()
<< pred_text << "(" << e1 << ", " << e2 << ", " << e3
<< ") evaluates to false, where"
<< "\n"
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
<< e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
<< e3 << " evaluates to " << ::testing::PrintToString(v3);
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
// Don't use this in your code.
#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
// this in your code.
#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
#v1, \
#v2, \
#v3, \
pred, \
v1, \
v2, \
v3), on_failure)
// Ternary predicate assertion macros.
#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED3(pred, v1, v2, v3) \
GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED3(pred, v1, v2, v3) \
GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
// this in your code.
template <typename Pred,
typename T1,
typename T2,
typename T3,
typename T4>
AssertionResult AssertPred4Helper(const char* pred_text,
const char* e1,
const char* e2,
const char* e3,
const char* e4,
Pred pred,
const T1& v1,
const T2& v2,
const T3& v3,
const T4& v4) {
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
return AssertionFailure()
<< pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
<< ") evaluates to false, where"
<< "\n"
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
<< e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
<< e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
<< e4 << " evaluates to " << ::testing::PrintToString(v4);
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
// Don't use this in your code.
#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
// this in your code.
#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
#v1, \
#v2, \
#v3, \
#v4, \
pred, \
v1, \
v2, \
v3, \
v4), on_failure)
// 4-ary predicate assertion macros.
#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
// this in your code.
template <typename Pred,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
AssertionResult AssertPred5Helper(const char* pred_text,
const char* e1,
const char* e2,
const char* e3,
const char* e4,
const char* e5,
Pred pred,
const T1& v1,
const T2& v2,
const T3& v3,
const T4& v4,
const T5& v5) {
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
return AssertionFailure()
<< pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
<< ", " << e5 << ") evaluates to false, where"
<< "\n"
<< e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
<< e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
<< e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
<< e4 << " evaluates to " << ::testing::PrintToString(v4) << "\n"
<< e5 << " evaluates to " << ::testing::PrintToString(v5);
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
// Don't use this in your code.
#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
on_failure)
// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
// this in your code.
#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
#v1, \
#v2, \
#v3, \
#v4, \
#v5, \
pred, \
v1, \
v2, \
v3, \
v4, \
v5), on_failure)
// 5-ary predicate assertion macros.
#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
-61
View File
@@ -1,61 +0,0 @@
// Copyright 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Google C++ Testing and Mocking Framework definitions useful in production code.
// GOOGLETEST_CM0003 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
// When you need to test the private or protected members of a class,
// use the FRIEND_TEST macro to declare your tests as friends of the
// class. For example:
//
// class MyClass {
// private:
// void PrivateMethod();
// FRIEND_TEST(MyClassTest, PrivateMethodWorks);
// };
//
// class MyClassTest : public testing::Test {
// // ...
// };
//
// TEST_F(MyClassTest, PrivateMethodWorks) {
// // Can call MyClass::PrivateMethod() here.
// }
//
// Note: The test class must be in the same namespace as the class being tested.
// For example, putting MyClassTest in an anonymous namespace will not work.
#define FRIEND_TEST(test_case_name, test_name)\
friend class test_case_name##_##test_name##_Test
#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
-56
View File
@@ -1,56 +0,0 @@
# Customization Points
The custom directory is an injection point for custom user configurations.
## Header `gtest.h`
### The following macros can be defined:
* `GTEST_OS_STACK_TRACE_GETTER_` - The name of an implementation of
`OsStackTraceGetterInterface`.
* `GTEST_CUSTOM_TEMPDIR_FUNCTION_` - An override for `testing::TempDir()`. See
`testing::TempDir` for semantics and signature.
## Header `gtest-port.h`
The following macros can be defined:
### Flag related macros:
* `GTEST_FLAG(flag_name)`
* `GTEST_USE_OWN_FLAGFILE_FLAG_` - Define to 0 when the system provides its
own flagfile flag parsing.
* `GTEST_DECLARE_bool_(name)`
* `GTEST_DECLARE_int32_(name)`
* `GTEST_DECLARE_string_(name)`
* `GTEST_DEFINE_bool_(name, default_val, doc)`
* `GTEST_DEFINE_int32_(name, default_val, doc)`
* `GTEST_DEFINE_string_(name, default_val, doc)`
### Logging:
* `GTEST_LOG_(severity)`
* `GTEST_CHECK_(condition)`
* Functions `LogToStderr()` and `FlushInfoLog()` have to be provided too.
### Threading:
* `GTEST_HAS_NOTIFICATION_` - Enabled if Notification is already provided.
* `GTEST_HAS_MUTEX_AND_THREAD_LOCAL_` - Enabled if `Mutex` and `ThreadLocal`
are already provided. Must also provide `GTEST_DECLARE_STATIC_MUTEX_(mutex)`
and `GTEST_DEFINE_STATIC_MUTEX_(mutex)`
* `GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)`
* `GTEST_LOCK_EXCLUDED_(locks)`
### Underlying library support features
* `GTEST_HAS_CXXABI_H_`
### Exporting API symbols:
* `GTEST_API_` - Specifier for exported symbols.
## Header `gtest-printers.h`
* See documentation at `gtest/gtest-printers.h` for details on how to define a
custom printer.
@@ -1,37 +0,0 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Injection point for custom user configurations. See README for details
//
// ** Custom implementation starts here **
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
@@ -1,42 +0,0 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// This file provides an injection point for custom printers in a local
// installation of gTest.
// It will be included from gtest-printers.h and the overrides in this file
// will be visible to everyone.
//
// Injection point for custom user configurations. See README for details
//
// ** Custom implementation starts here **
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
-37
View File
@@ -1,37 +0,0 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Injection point for custom user configurations. See README for details
//
// ** Custom implementation starts here **
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
@@ -1,303 +0,0 @@
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The Google C++ Testing and Mocking Framework (Google Test)
//
// This header file defines internal utilities needed for implementing
// death tests. They are subject to change without notice.
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
#include <stdio.h>
#include <memory>
#include "../gtest-matchers.h"
#include "gtest-internal.h"
namespace testing {
namespace internal {
GTEST_DECLARE_string_(internal_run_death_test);
// Names of the flags (needed for parsing Google Test flags).
const char kDeathTestStyleFlag[] = "death_test_style";
const char kDeathTestUseFork[] = "death_test_use_fork";
const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
#if GTEST_HAS_DEATH_TEST
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
/* class A needs to have dll-interface to be used by clients of class B */)
// DeathTest is a class that hides much of the complexity of the
// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method
// returns a concrete class that depends on the prevailing death test
// style, as defined by the --gtest_death_test_style and/or
// --gtest_internal_run_death_test flags.
// In describing the results of death tests, these terms are used with
// the corresponding definitions:
//
// exit status: The integer exit information in the format specified
// by wait(2)
// exit code: The integer code passed to exit(3), _exit(2), or
// returned from main()
class GTEST_API_ DeathTest {
public:
// Create returns false if there was an error determining the
// appropriate action to take for the current death test; for example,
// if the gtest_death_test_style flag is set to an invalid value.
// The LastMessage method will return a more detailed message in that
// case. Otherwise, the DeathTest pointer pointed to by the "test"
// argument is set. If the death test should be skipped, the pointer
// is set to NULL; otherwise, it is set to the address of a new concrete
// DeathTest object that controls the execution of the current test.
static bool Create(const char* statement, Matcher<const std::string&> matcher,
const char* file, int line, DeathTest** test);
DeathTest();
virtual ~DeathTest() { }
// A helper class that aborts a death test when it's deleted.
class ReturnSentinel {
public:
explicit ReturnSentinel(DeathTest* test) : test_(test) { }
~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
private:
DeathTest* const test_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
} GTEST_ATTRIBUTE_UNUSED_;
// An enumeration of possible roles that may be taken when a death
// test is encountered. EXECUTE means that the death test logic should
// be executed immediately. OVERSEE means that the program should prepare
// the appropriate environment for a child process to execute the death
// test, then wait for it to complete.
enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
// An enumeration of the three reasons that a test might be aborted.
enum AbortReason {
TEST_ENCOUNTERED_RETURN_STATEMENT,
TEST_THREW_EXCEPTION,
TEST_DID_NOT_DIE
};
// Assumes one of the above roles.
virtual TestRole AssumeRole() = 0;
// Waits for the death test to finish and returns its status.
virtual int Wait() = 0;
// Returns true if the death test passed; that is, the test process
// exited during the test, its exit status matches a user-supplied
// predicate, and its stderr output matches a user-supplied regular
// expression.
// The user-supplied predicate may be a macro expression rather
// than a function pointer or functor, or else Wait and Passed could
// be combined.
virtual bool Passed(bool exit_status_ok) = 0;
// Signals that the death test did not die as expected.
virtual void Abort(AbortReason reason) = 0;
// Returns a human-readable outcome message regarding the outcome of
// the last death test.
static const char* LastMessage();
static void set_last_death_test_message(const std::string& message);
private:
// A string containing a description of the outcome of the last death test.
static std::string last_death_test_message_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
};
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
// Factory interface for death tests. May be mocked out for testing.
class DeathTestFactory {
public:
virtual ~DeathTestFactory() { }
virtual bool Create(const char* statement,
Matcher<const std::string&> matcher, const char* file,
int line, DeathTest** test) = 0;
};
// A concrete DeathTestFactory implementation for normal use.
class DefaultDeathTestFactory : public DeathTestFactory {
public:
bool Create(const char* statement, Matcher<const std::string&> matcher,
const char* file, int line, DeathTest** test) override;
};
// Returns true if exit_status describes a process that was terminated
// by a signal, or exited normally with a nonzero exit code.
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads
// and interpreted as a regex (rather than an Eq matcher) for legacy
// compatibility.
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
::testing::internal::RE regex) {
return ContainsRegex(regex.pattern());
}
inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
return ContainsRegex(regex);
}
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
const ::std::string& regex) {
return ContainsRegex(regex);
}
// If a Matcher<const ::std::string&> is passed to EXPECT_DEATH (etc.), it's
// used directly.
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
Matcher<const ::std::string&> matcher) {
return matcher;
}
// Traps C++ exceptions escaping statement and reports them as test
// failures. Note that trapping SEH exceptions is not implemented here.
# if GTEST_HAS_EXCEPTIONS
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} catch (const ::std::exception& gtest_exception) { \
fprintf(\
stderr, \
"\n%s: Caught std::exception-derived exception escaping the " \
"death test statement. Exception message: %s\n", \
::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
gtest_exception.what()); \
fflush(stderr); \
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
} catch (...) { \
death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
}
# else
# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
# endif
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
// ASSERT_EXIT*, and EXPECT_EXIT*.
#define GTEST_DEATH_TEST_(statement, predicate, regex_or_matcher, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
::testing::internal::DeathTest* gtest_dt; \
if (!::testing::internal::DeathTest::Create( \
#statement, \
::testing::internal::MakeDeathTestMatcher(regex_or_matcher), \
__FILE__, __LINE__, &gtest_dt)) { \
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
} \
if (gtest_dt != nullptr) { \
std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \
switch (gtest_dt->AssumeRole()) { \
case ::testing::internal::DeathTest::OVERSEE_TEST: \
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
} \
break; \
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
::testing::internal::DeathTest::ReturnSentinel gtest_sentinel( \
gtest_dt); \
GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
break; \
} \
default: \
break; \
} \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__) \
: fail(::testing::internal::DeathTest::LastMessage())
// The symbol "fail" here expands to something into which a message
// can be streamed.
// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
// NDEBUG mode. In this case we need the statements to be executed and the macro
// must accept a streamed message even though the message is never printed.
// The regex object is not evaluated, but it is used to prevent "unused"
// warnings and to avoid an expression that doesn't compile in debug mode.
#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} else if (!::testing::internal::AlwaysTrue()) { \
::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
} else \
::testing::Message()
// A class representing the parsed contents of the
// --gtest_internal_run_death_test flag, as it existed when
// RUN_ALL_TESTS was called.
class InternalRunDeathTestFlag {
public:
InternalRunDeathTestFlag(const std::string& a_file,
int a_line,
int an_index,
int a_write_fd)
: file_(a_file), line_(a_line), index_(an_index),
write_fd_(a_write_fd) {}
~InternalRunDeathTestFlag() {
if (write_fd_ >= 0)
posix::Close(write_fd_);
}
const std::string& file() const { return file_; }
int line() const { return line_; }
int index() const { return index_; }
int write_fd() const { return write_fd_; }
private:
std::string file_;
int line_;
int index_;
int write_fd_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
};
// Returns a newly created InternalRunDeathTestFlag object with fields
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
// the flag is specified; otherwise returns NULL.
InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
#endif // GTEST_HAS_DEATH_TEST
} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
-211
View File
@@ -1,211 +0,0 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Google Test filepath utilities
//
// This header file declares classes and functions used internally by
// Google Test. They are subject to change without notice.
//
// This file is #included in gtest/internal/gtest-internal.h.
// Do not include this header file separately!
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
#include "gtest-string.h"
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
/* class A needs to have dll-interface to be used by clients of class B */)
namespace testing {
namespace internal {
// FilePath - a class for file and directory pathname manipulation which
// handles platform-specific conventions (like the pathname separator).
// Used for helper functions for naming files in a directory for xml output.
// Except for Set methods, all methods are const or static, which provides an
// "immutable value object" -- useful for peace of mind.
// A FilePath with a value ending in a path separator ("like/this/") represents
// a directory, otherwise it is assumed to represent a file. In either case,
// it may or may not represent an actual file or directory in the file system.
// Names are NOT checked for syntax correctness -- no checking for illegal
// characters, malformed paths, etc.
class GTEST_API_ FilePath {
public:
FilePath() : pathname_("") { }
FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
explicit FilePath(const std::string& pathname) : pathname_(pathname) {
Normalize();
}
FilePath& operator=(const FilePath& rhs) {
Set(rhs);
return *this;
}
void Set(const FilePath& rhs) {
pathname_ = rhs.pathname_;
}
const std::string& string() const { return pathname_; }
const char* c_str() const { return pathname_.c_str(); }
// Returns the current working directory, or "" if unsuccessful.
static FilePath GetCurrentDir();
// Given directory = "dir", base_name = "test", number = 0,
// extension = "xml", returns "dir/test.xml". If number is greater
// than zero (e.g., 12), returns "dir/test_12.xml".
// On Windows platform, uses \ as the separator rather than /.
static FilePath MakeFileName(const FilePath& directory,
const FilePath& base_name,
int number,
const char* extension);
// Given directory = "dir", relative_path = "test.xml",
// returns "dir/test.xml".
// On Windows, uses \ as the separator rather than /.
static FilePath ConcatPaths(const FilePath& directory,
const FilePath& relative_path);
// Returns a pathname for a file that does not currently exist. The pathname
// will be directory/base_name.extension or
// directory/base_name_<number>.extension if directory/base_name.extension
// already exists. The number will be incremented until a pathname is found
// that does not already exist.
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
// There could be a race condition if two or more processes are calling this
// function at the same time -- they could both pick the same filename.
static FilePath GenerateUniqueFileName(const FilePath& directory,
const FilePath& base_name,
const char* extension);
// Returns true if and only if the path is "".
bool IsEmpty() const { return pathname_.empty(); }
// If input name has a trailing separator character, removes it and returns
// the name, otherwise return the name string unmodified.
// On Windows platform, uses \ as the separator, other platforms use /.
FilePath RemoveTrailingPathSeparator() const;
// Returns a copy of the FilePath with the directory part removed.
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
// returns an empty FilePath ("").
// On Windows platform, '\' is the path separator, otherwise it is '/'.
FilePath RemoveDirectoryName() const;
// RemoveFileName returns the directory path with the filename removed.
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
// On Windows platform, '\' is the path separator, otherwise it is '/'.
FilePath RemoveFileName() const;
// Returns a copy of the FilePath with the case-insensitive extension removed.
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
// FilePath("dir/file"). If a case-insensitive extension is not
// found, returns a copy of the original FilePath.
FilePath RemoveExtension(const char* extension) const;
// Creates directories so that path exists. Returns true if successful or if
// the directories already exist; returns false if unable to create
// directories for any reason. Will also return false if the FilePath does
// not represent a directory (that is, it doesn't end with a path separator).
bool CreateDirectoriesRecursively() const;
// Create the directory so that path exists. Returns true if successful or
// if the directory already exists; returns false if unable to create the
// directory for any reason, including if the parent directory does not
// exist. Not named "CreateDirectory" because that's a macro on Windows.
bool CreateFolder() const;
// Returns true if FilePath describes something in the file-system,
// either a file, directory, or whatever, and that something exists.
bool FileOrDirectoryExists() const;
// Returns true if pathname describes a directory in the file-system
// that exists.
bool DirectoryExists() const;
// Returns true if FilePath ends with a path separator, which indicates that
// it is intended to represent a directory. Returns false otherwise.
// This does NOT check that a directory (or file) actually exists.
bool IsDirectory() const;
// Returns true if pathname describes a root directory. (Windows has one
// root directory per disk drive.)
bool IsRootDirectory() const;
// Returns true if pathname describes an absolute path.
bool IsAbsolutePath() const;
private:
// Replaces multiple consecutive separators with a single separator.
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
// redundancies that might be in a pathname involving "." or "..".
//
// A pathname with multiple consecutive separators may occur either through
// user error or as a result of some scripts or APIs that generate a pathname
// with a trailing separator. On other platforms the same API or script
// may NOT generate a pathname with a trailing "/". Then elsewhere that
// pathname may have another "/" and pathname components added to it,
// without checking for the separator already being there.
// The script language and operating system may allow paths like "foo//bar"
// but some of the functions in FilePath will not handle that correctly. In
// particular, RemoveTrailingPathSeparator() only removes one separator, and
// it is called in CreateDirectoriesRecursively() assuming that it will change
// a pathname from directory syntax (trailing separator) to filename syntax.
//
// On Windows this method also replaces the alternate path separator '/' with
// the primary path separator '\\', so that for example "bar\\/\\foo" becomes
// "bar\\foo".
void Normalize();
// Returns a pointer to the last occurence of a valid path separator in
// the FilePath. On Windows, for example, both '/' and '\' are valid path
// separators. Returns NULL if no path separator was found.
const char* FindLastPathSeparator() const;
std::string pathname_;
}; // class FilePath
} // namespace internal
} // namespace testing
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
File diff suppressed because it is too large. Load diff
-880
View File
@@ -1,880 +0,0 @@
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Type and function utilities for implementing parameterized tests.
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
#include <ctype.h>
#include <cassert>
#include <iterator>
#include <memory>
#include <set>
#include <tuple>
#include <utility>
#include <vector>
#include "../gtest-printers.h"
#include "gtest-internal.h"
#include "gtest-port.h"
namespace testing {
// Input to a parameterized test name generator, describing a test parameter.
// Consists of the parameter value and the integer parameter index.
template <class ParamType>
struct TestParamInfo {
TestParamInfo(const ParamType& a_param, size_t an_index) :
param(a_param),
index(an_index) {}
ParamType param;
size_t index;
};
// A builtin parameterized test name generator which returns the result of
// testing::PrintToString.
struct PrintToStringParamName {
template <class ParamType>
std::string operator()(const TestParamInfo<ParamType>& info) const {
return PrintToString(info.param);
}
};
namespace internal {
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
// Utility Functions
// Outputs a message explaining invalid registration of different
// fixture class for the same test suite. This may happen when
// TEST_P macro is used to define two tests with the same name
// but in different namespaces.
GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
CodeLocation code_location);
template <typename> class ParamGeneratorInterface;
template <typename> class ParamGenerator;
// Interface for iterating over elements provided by an implementation
// of ParamGeneratorInterface<T>.
template <typename T>
class ParamIteratorInterface {
public:
virtual ~ParamIteratorInterface() {}
// A pointer to the base generator instance.
// Used only for the purposes of iterator comparison
// to make sure that two iterators belong to the same generator.
virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
// Advances iterator to point to the next element
// provided by the generator. The caller is responsible
// for not calling Advance() on an iterator equal to
// BaseGenerator()->End().
virtual void Advance() = 0;
// Clones the iterator object. Used for implementing copy semantics
// of ParamIterator<T>.
virtual ParamIteratorInterface* Clone() const = 0;
// Dereferences the current iterator and provides (read-only) access
// to the pointed value. It is the caller's responsibility not to call
// Current() on an iterator equal to BaseGenerator()->End().
// Used for implementing ParamGenerator<T>::operator*().
virtual const T* Current() const = 0;
// Determines whether the given iterator and other point to the same
// element in the sequence generated by the generator.
// Used for implementing ParamGenerator<T>::operator==().
virtual bool Equals(const ParamIteratorInterface& other) const = 0;
};
// Class iterating over elements provided by an implementation of
// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
// and implements the const forward iterator concept.
template <typename T>
class ParamIterator {
public:
typedef T value_type;
typedef const T& reference;
typedef ptrdiff_t difference_type;
// ParamIterator assumes ownership of the impl_ pointer.
ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
ParamIterator& operator=(const ParamIterator& other) {
if (this != &other)
impl_.reset(other.impl_->Clone());
return *this;
}
const T& operator*() const { return *impl_->Current(); }
const T* operator->() const { return impl_->Current(); }
// Prefix version of operator++.
ParamIterator& operator++() {
impl_->Advance();
return *this;
}
// Postfix version of operator++.
ParamIterator operator++(int /*unused*/) {
ParamIteratorInterface<T>* clone = impl_->Clone();
impl_->Advance();
return ParamIterator(clone);
}
bool operator==(const ParamIterator& other) const {
return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
}
bool operator!=(const ParamIterator& other) const {
return !(*this == other);
}
private:
friend class ParamGenerator<T>;
explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
std::unique_ptr<ParamIteratorInterface<T> > impl_;
};
// ParamGeneratorInterface<T> is the binary interface to access generators
// defined in other translation units.
template <typename T>
class ParamGeneratorInterface {
public:
typedef T ParamType;
virtual ~ParamGeneratorInterface() {}
// Generator interface definition
virtual ParamIteratorInterface<T>* Begin() const = 0;
virtual ParamIteratorInterface<T>* End() const = 0;
};
// Wraps ParamGeneratorInterface<T> and provides general generator syntax
// compatible with the STL Container concept.
// This class implements copy initialization semantics and the contained
// ParamGeneratorInterface<T> instance is shared among all copies
// of the original object. This is possible because that instance is immutable.
template<typename T>
class ParamGenerator {
public:
typedef ParamIterator<T> iterator;
explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
ParamGenerator& operator=(const ParamGenerator& other) {
impl_ = other.impl_;
return *this;
}
iterator begin() const { return iterator(impl_->Begin()); }
iterator end() const { return iterator(impl_->End()); }
private:
std::shared_ptr<const ParamGeneratorInterface<T> > impl_;
};
// Generates values from a range of two comparable values. Can be used to
// generate sequences of user-defined types that implement operator+() and
// operator<().
// This class is used in the Range() function.
template <typename T, typename IncrementT>
class RangeGenerator : public ParamGeneratorInterface<T> {
public:
RangeGenerator(T begin, T end, IncrementT step)
: begin_(begin), end_(end),
step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
~RangeGenerator() override {}
ParamIteratorInterface<T>* Begin() const override {
return new Iterator(this, begin_, 0, step_);
}
ParamIteratorInterface<T>* End() const override {
return new Iterator(this, end_, end_index_, step_);
}
private:
class Iterator : public ParamIteratorInterface<T> {
public:
Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
IncrementT step)
: base_(base), value_(value), index_(index), step_(step) {}
~Iterator() override {}
const ParamGeneratorInterface<T>* BaseGenerator() const override {
return base_;
}
void Advance() override {
value_ = static_cast<T>(value_ + step_);
index_++;
}
ParamIteratorInterface<T>* Clone() const override {
return new Iterator(*this);
}
const T* Current() const override { return &value_; }
bool Equals(const ParamIteratorInterface<T>& other) const override {
// Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
<< "The program attempted to compare iterators "
<< "from different generators." << std::endl;
const int other_index =
CheckedDowncastToActualType<const Iterator>(&other)->index_;
return index_ == other_index;
}
private:
Iterator(const Iterator& other)
: ParamIteratorInterface<T>(),
base_(other.base_), value_(other.value_), index_(other.index_),
step_(other.step_) {}
// No implementation - assignment is unsupported.
void operator=(const Iterator& other);
const ParamGeneratorInterface<T>* const base_;
T value_;
int index_;
const IncrementT step_;
}; // class RangeGenerator::Iterator
static int CalculateEndIndex(const T& begin,
const T& end,
const IncrementT& step) {
int end_index = 0;
for (T i = begin; i < end; i = static_cast<T>(i + step))
end_index++;
return end_index;
}
// No implementation - assignment is unsupported.
void operator=(const RangeGenerator& other);
const T begin_;
const T end_;
const IncrementT step_;
// The index for the end() iterator. All the elements in the generated
// sequence are indexed (0-based) to aid iterator comparison.
const int end_index_;
}; // class RangeGenerator
// Generates values from a pair of STL-style iterators. Used in the
// ValuesIn() function. The elements are copied from the source range
// since the source can be located on the stack, and the generator
// is likely to persist beyond that stack frame.
template <typename T>
class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
public:
template <typename ForwardIterator>
ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
: container_(begin, end) {}
~ValuesInIteratorRangeGenerator() override {}
ParamIteratorInterface<T>* Begin() const override {
return new Iterator(this, container_.begin());
}
ParamIteratorInterface<T>* End() const override {
return new Iterator(this, container_.end());
}
private:
typedef typename ::std::vector<T> ContainerType;
class Iterator : public ParamIteratorInterface<T> {
public:
Iterator(const ParamGeneratorInterface<T>* base,
typename ContainerType::const_iterator iterator)
: base_(base), iterator_(iterator) {}
~Iterator() override {}
const ParamGeneratorInterface<T>* BaseGenerator() const override {
return base_;
}
void Advance() override {
++iterator_;
value_.reset();
}
ParamIteratorInterface<T>* Clone() const override {
return new Iterator(*this);
}
// We need to use cached value referenced by iterator_ because *iterator_
// can return a temporary object (and of type other then T), so just
// having "return &*iterator_;" doesn't work.
// value_ is updated here and not in Advance() because Advance()
// can advance iterator_ beyond the end of the range, and we cannot
// detect that fact. The client code, on the other hand, is
// responsible for not calling Current() on an out-of-range iterator.
const T* Current() const override {
if (value_.get() == nullptr) value_.reset(new T(*iterator_));
return value_.get();
}
bool Equals(const ParamIteratorInterface<T>& other) const override {
// Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
<< "The program attempted to compare iterators "
<< "from different generators." << std::endl;
return iterator_ ==
CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
}
private:
Iterator(const Iterator& other)
// The explicit constructor call suppresses a false warning
// emitted by gcc when supplied with the -Wextra option.
: ParamIteratorInterface<T>(),
base_(other.base_),
iterator_(other.iterator_) {}
const ParamGeneratorInterface<T>* const base_;
typename ContainerType::const_iterator iterator_;
// A cached value of *iterator_. We keep it here to allow access by
// pointer in the wrapping iterator's operator->().
// value_ needs to be mutable to be accessed in Current().
// Use of std::unique_ptr helps manage cached value's lifetime,
// which is bound by the lifespan of the iterator itself.
mutable std::unique_ptr<const T> value_;
}; // class ValuesInIteratorRangeGenerator::Iterator
// No implementation - assignment is unsupported.
void operator=(const ValuesInIteratorRangeGenerator& other);
const ContainerType container_;
}; // class ValuesInIteratorRangeGenerator
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Default parameterized test name generator, returns a string containing the
// integer test parameter index.
template <class ParamType>
std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
Message name_stream;
name_stream << info.index;
return name_stream.GetString();
}
template <typename T = int>
void TestNotEmpty() {
static_assert(sizeof(T) == 0, "Empty arguments are not allowed.");
}
template <typename T = int>
void TestNotEmpty(const T&) {}
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Stores a parameter value and later creates tests parameterized with that
// value.
template <class TestClass>
class ParameterizedTestFactory : public TestFactoryBase {
public:
typedef typename TestClass::ParamType ParamType;
explicit ParameterizedTestFactory(ParamType parameter) :
parameter_(parameter) {}
Test* CreateTest() override {
TestClass::SetParam(&parameter_);
return new TestClass();
}
private:
const ParamType parameter_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
};
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// TestMetaFactoryBase is a base class for meta-factories that create
// test factories for passing into MakeAndRegisterTestInfo function.
template <class ParamType>
class TestMetaFactoryBase {
public:
virtual ~TestMetaFactoryBase() {}
virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
};
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// TestMetaFactory creates test factories for passing into
// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
// ownership of test factory pointer, same factory object cannot be passed
// into that method twice. But ParameterizedTestSuiteInfo is going to call
// it for each Test/Parameter value combination. Thus it needs meta factory
// creator class.
template <class TestSuite>
class TestMetaFactory
: public TestMetaFactoryBase<typename TestSuite::ParamType> {
public:
using ParamType = typename TestSuite::ParamType;
TestMetaFactory() {}
TestFactoryBase* CreateTestFactory(ParamType parameter) override {
return new ParameterizedTestFactory<TestSuite>(parameter);
}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
};
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// ParameterizedTestSuiteInfoBase is a generic interface
// to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase
// accumulates test information provided by TEST_P macro invocations
// and generators provided by INSTANTIATE_TEST_SUITE_P macro invocations
// and uses that information to register all resulting test instances
// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds
// a collection of pointers to the ParameterizedTestSuiteInfo objects
// and calls RegisterTests() on each of them when asked.
class ParameterizedTestSuiteInfoBase {
public:
virtual ~ParameterizedTestSuiteInfoBase() {}
// Base part of test suite name for display purposes.
virtual const std::string& GetTestSuiteName() const = 0;
// Test case id to verify identity.
virtual TypeId GetTestSuiteTypeId() const = 0;
// UnitTest class invokes this method to register tests in this
// test suite right before running them in RUN_ALL_TESTS macro.
// This method should not be called more than once on any single
// instance of a ParameterizedTestSuiteInfoBase derived class.
virtual void RegisterTests() = 0;
protected:
ParameterizedTestSuiteInfoBase() {}
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase);
};
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P
// macro invocations for a particular test suite and generators
// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that
// test suite. It registers tests with all values generated by all
// generators when asked.
template <class TestSuite>
class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
public:
// ParamType and GeneratorCreationFunc are private types but are required
// for declarations of public methods AddTestPattern() and
// AddTestSuiteInstantiation().
using ParamType = typename TestSuite::ParamType;
// A function that returns an instance of appropriate generator type.
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
explicit ParameterizedTestSuiteInfo(const char* name,
CodeLocation code_location)
: test_suite_name_(name), code_location_(code_location) {}
// Test case base name for display purposes.
const std::string& GetTestSuiteName() const override {
return test_suite_name_;
}
// Test case id to verify identity.
TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); }
// TEST_P macro uses AddTestPattern() to record information
// about a single test in a LocalTestInfo structure.
// test_suite_name is the base name of the test suite (without invocation
// prefix). test_base_name is the name of an individual test without
// parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
// test suite base name and DoBar is test base name.
void AddTestPattern(const char* test_suite_name, const char* test_base_name,
TestMetaFactoryBase<ParamType>* meta_factory) {
tests_.push_back(std::shared_ptr<TestInfo>(
new TestInfo(test_suite_name, test_base_name, meta_factory)));
}
// INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
// about a generator.
int AddTestSuiteInstantiation(const std::string& instantiation_name,
GeneratorCreationFunc* func,
ParamNameGeneratorFunc* name_func,
const char* file, int line) {
instantiations_.push_back(
InstantiationInfo(instantiation_name, func, name_func, file, line));
return 0; // Return value used only to run this method in namespace scope.
}
// UnitTest class invokes this method to register tests in this test suite
// test suites right before running tests in RUN_ALL_TESTS macro.
// This method should not be called more than once on any single
// instance of a ParameterizedTestSuiteInfoBase derived class.
// UnitTest has a guard to prevent from calling this method more than once.
void RegisterTests() override {
for (typename TestInfoContainer::iterator test_it = tests_.begin();
test_it != tests_.end(); ++test_it) {
std::shared_ptr<TestInfo> test_info = *test_it;
for (typename InstantiationContainer::iterator gen_it =
instantiations_.begin(); gen_it != instantiations_.end();
++gen_it) {
const std::string& instantiation_name = gen_it->name;
ParamGenerator<ParamType> generator((*gen_it->generator)());
ParamNameGeneratorFunc* name_func = gen_it->name_func;
const char* file = gen_it->file;
int line = gen_it->line;
std::string test_suite_name;
if ( !instantiation_name.empty() )
test_suite_name = instantiation_name + "/";
test_suite_name += test_info->test_suite_base_name;
size_t i = 0;
std::set<std::string> test_param_names;
for (typename ParamGenerator<ParamType>::iterator param_it =
generator.begin();
param_it != generator.end(); ++param_it, ++i) {
Message test_name_stream;
std::string param_name = name_func(
TestParamInfo<ParamType>(*param_it, i));
GTEST_CHECK_(IsValidParamName(param_name))
<< "Parameterized test name '" << param_name
<< "' is invalid, in " << file
<< " line " << line << std::endl;
GTEST_CHECK_(test_param_names.count(param_name) == 0)
<< "Duplicate parameterized test name '" << param_name
<< "', in " << file << " line " << line << std::endl;
test_param_names.insert(param_name);
test_name_stream << test_info->test_base_name << "/" << param_name;
MakeAndRegisterTestInfo(
test_suite_name.c_str(), test_name_stream.GetString().c_str(),
nullptr, // No type parameter.
PrintToString(*param_it).c_str(), code_location_,
GetTestSuiteTypeId(),
SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
test_info->test_meta_factory->CreateTestFactory(*param_it));
} // for param_it
} // for gen_it
} // for test_it
} // RegisterTests
private:
// LocalTestInfo structure keeps information about a single test registered
// with TEST_P macro.
struct TestInfo {
TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
TestMetaFactoryBase<ParamType>* a_test_meta_factory)
: test_suite_base_name(a_test_suite_base_name),
test_base_name(a_test_base_name),
test_meta_factory(a_test_meta_factory) {}
const std::string test_suite_base_name;
const std::string test_base_name;
const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
};
using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >;
// Records data received from INSTANTIATE_TEST_SUITE_P macros:
// <Instantiation name, Sequence generator creation function,
// Name generator function, Source file, Source line>
struct InstantiationInfo {
InstantiationInfo(const std::string &name_in,
GeneratorCreationFunc* generator_in,
ParamNameGeneratorFunc* name_func_in,
const char* file_in,
int line_in)
: name(name_in),
generator(generator_in),
name_func(name_func_in),
file(file_in),
line(line_in) {}
std::string name;
GeneratorCreationFunc* generator;
ParamNameGeneratorFunc* name_func;
const char* file;
int line;
};
typedef ::std::vector<InstantiationInfo> InstantiationContainer;
static bool IsValidParamName(const std::string& name) {
// Check for empty string
if (name.empty())
return false;
// Check for invalid characters
for (std::string::size_type index = 0; index < name.size(); ++index) {
if (!isalnum(name[index]) && name[index] != '_')
return false;
}
return true;
}
const std::string test_suite_name_;
CodeLocation code_location_;
TestInfoContainer tests_;
InstantiationContainer instantiations_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfo);
}; // class ParameterizedTestSuiteInfo
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
template <class TestCase>
using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo<TestCase>;
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// ParameterizedTestSuiteRegistry contains a map of
// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P
// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding
// ParameterizedTestSuiteInfo descriptors.
class ParameterizedTestSuiteRegistry {
public:
ParameterizedTestSuiteRegistry() {}
~ParameterizedTestSuiteRegistry() {
for (auto& test_suite_info : test_suite_infos_) {
delete test_suite_info;
}
}
// Looks up or creates and returns a structure containing information about
// tests and instantiations of a particular test suite.
template <class TestSuite>
ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
const char* test_suite_name, CodeLocation code_location) {
ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
for (auto& test_suite_info : test_suite_infos_) {
if (test_suite_info->GetTestSuiteName() == test_suite_name) {
if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
// Complain about incorrect usage of Google Test facilities
// and terminate the program since we cannot guaranty correct
// test suite setup and tear-down in this case.
ReportInvalidTestSuiteType(test_suite_name, code_location);
posix::Abort();
} else {
// At this point we are sure that the object we found is of the same
// type we are looking for, so we downcast it to that type
// without further checks.
typed_test_info = CheckedDowncastToActualType<
ParameterizedTestSuiteInfo<TestSuite> >(test_suite_info);
}
break;
}
}
if (typed_test_info == nullptr) {
typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
test_suite_name, code_location);
test_suite_infos_.push_back(typed_test_info);
}
return typed_test_info;
}
void RegisterTests() {
for (auto& test_suite_info : test_suite_infos_) {
test_suite_info->RegisterTests();
}
}
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
template <class TestCase>
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
const char* test_case_name, CodeLocation code_location) {
return GetTestSuitePatternHolder<TestCase>(test_case_name, code_location);
}
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
private:
using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
TestSuiteInfoContainer test_suite_infos_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry);
};
} // namespace internal
// Forward declarations of ValuesIn(), which is implemented in
// include/gtest/gtest-param-test.h.
template <class Container>
internal::ParamGenerator<typename Container::value_type> ValuesIn(
const Container& container);
namespace internal {
// Used in the Values() function to provide polymorphic capabilities.
template <typename... Ts>
class ValueArray {
public:
ValueArray(Ts... v) : v_{std::move(v)...} {}
template <typename T>
operator ParamGenerator<T>() const { // NOLINT
return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>()));
}
private:
template <typename T, size_t... I>
std::vector<T> MakeVector(IndexSequence<I...>) const {
return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
}
FlatTuple<Ts...> v_;
};
template <typename... T>
class CartesianProductGenerator
: public ParamGeneratorInterface<::std::tuple<T...>> {
public:
typedef ::std::tuple<T...> ParamType;
CartesianProductGenerator(const std::tuple<ParamGenerator<T>...>& g)
: generators_(g) {}
~CartesianProductGenerator() override {}
ParamIteratorInterface<ParamType>* Begin() const override {
return new Iterator(this, generators_, false);
}
ParamIteratorInterface<ParamType>* End() const override {
return new Iterator(this, generators_, true);
}
private:
template <class I>
class IteratorImpl;
template <size_t... I>
class IteratorImpl<IndexSequence<I...>>
: public ParamIteratorInterface<ParamType> {
public:
IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
const std::tuple<ParamGenerator<T>...>& generators, bool is_end)
: base_(base),
begin_(std::get<I>(generators).begin()...),
end_(std::get<I>(generators).end()...),
current_(is_end ? end_ : begin_) {
ComputeCurrentValue();
}
~IteratorImpl() override {}
const ParamGeneratorInterface<ParamType>* BaseGenerator() const override {
return base_;
}
// Advance should not be called on beyond-of-range iterators
// so no component iterators must be beyond end of range, either.
void Advance() override {
assert(!AtEnd());
// Advance the last iterator.
++std::get<sizeof...(T) - 1>(current_);
// if that reaches end, propagate that up.
AdvanceIfEnd<sizeof...(T) - 1>();
ComputeCurrentValue();
}
ParamIteratorInterface<ParamType>* Clone() const override {
return new IteratorImpl(*this);
}
const ParamType* Current() const override { return current_value_.get(); }
bool Equals(const ParamIteratorInterface<ParamType>& other) const override {
// Having the same base generator guarantees that the other
// iterator is of the same type and we can downcast.
GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
<< "The program attempted to compare iterators "
<< "from different generators." << std::endl;
const IteratorImpl* typed_other =
CheckedDowncastToActualType<const IteratorImpl>(&other);
// We must report iterators equal if they both point beyond their
// respective ranges. That can happen in a variety of fashions,
// so we have to consult AtEnd().
if (AtEnd() && typed_other->AtEnd()) return true;
bool same = true;
bool dummy[] = {
(same = same && std::get<I>(current_) ==
std::get<I>(typed_other->current_))...};
(void)dummy;
return same;
}
private:
template <size_t ThisI>
void AdvanceIfEnd() {
if (std::get<ThisI>(current_) != std::get<ThisI>(end_)) return;
bool last = ThisI == 0;
if (last) {
// We are done. Nothing else to propagate.
return;
}
constexpr size_t NextI = ThisI - (ThisI != 0);
std::get<ThisI>(current_) = std::get<ThisI>(begin_);
++std::get<NextI>(current_);
AdvanceIfEnd<NextI>();
}
void ComputeCurrentValue() {
if (!AtEnd())
current_value_ = std::make_shared<ParamType>(*std::get<I>(current_)...);
}
bool AtEnd() const {
bool at_end = false;
bool dummy[] = {
(at_end = at_end || std::get<I>(current_) == std::get<I>(end_))...};
(void)dummy;
return at_end;
}
const ParamGeneratorInterface<ParamType>* const base_;
std::tuple<typename ParamGenerator<T>::iterator...> begin_;
std::tuple<typename ParamGenerator<T>::iterator...> end_;
std::tuple<typename ParamGenerator<T>::iterator...> current_;
std::shared_ptr<ParamType> current_value_;
};
using Iterator = IteratorImpl<typename MakeIndexSequence<sizeof...(T)>::type>;
std::tuple<ParamGenerator<T>...> generators_;
};
template <class... Gen>
class CartesianProductHolder {
public:
CartesianProductHolder(const Gen&... g) : generators_(g...) {}
template <typename... T>
operator ParamGenerator<::std::tuple<T...>>() const {
return ParamGenerator<::std::tuple<T...>>(
new CartesianProductGenerator<T...>(generators_));
}
private:
std::tuple<Gen...> generators_;
};
} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
-111
View File
@@ -1,111 +0,0 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The Google C++ Testing and Mocking Framework (Google Test)
//
// This header file defines the GTEST_OS_* macro.
// It is separate from gtest-port.h so that custom/gtest-port.h can include it.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
// Determines the platform on which Google Test is compiled.
#ifdef __CYGWIN__
# define GTEST_OS_CYGWIN 1
# elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)
# define GTEST_OS_WINDOWS_MINGW 1
# define GTEST_OS_WINDOWS 1
#elif defined _WIN32
# define GTEST_OS_WINDOWS 1
# ifdef _WIN32_WCE
# define GTEST_OS_WINDOWS_MOBILE 1
# elif defined(WINAPI_FAMILY)
# include <winapifamily.h>
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# define GTEST_OS_WINDOWS_DESKTOP 1
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
# define GTEST_OS_WINDOWS_PHONE 1
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
# define GTEST_OS_WINDOWS_RT 1
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
# define GTEST_OS_WINDOWS_PHONE 1
# define GTEST_OS_WINDOWS_TV_TITLE 1
# else
// WINAPI_FAMILY defined but no known partition matched.
// Default to desktop.
# define GTEST_OS_WINDOWS_DESKTOP 1
# endif
# else
# define GTEST_OS_WINDOWS_DESKTOP 1
# endif // _WIN32_WCE
#elif defined __OS2__
# define GTEST_OS_OS2 1
#elif defined __APPLE__
# define GTEST_OS_MAC 1
# if TARGET_OS_IPHONE
# define GTEST_OS_IOS 1
# endif
#elif defined __DragonFly__
# define GTEST_OS_DRAGONFLY 1
#elif defined __FreeBSD__
# define GTEST_OS_FREEBSD 1
#elif defined __Fuchsia__
# define GTEST_OS_FUCHSIA 1
#elif defined(__GLIBC__) && defined(__FreeBSD_kernel__)
# define GTEST_OS_GNU_KFREEBSD 1
#elif defined __linux__
# define GTEST_OS_LINUX 1
# if defined __ANDROID__
# define GTEST_OS_LINUX_ANDROID 1
# endif
#elif defined __MVS__
# define GTEST_OS_ZOS 1
#elif defined(__sun) && defined(__SVR4)
# define GTEST_OS_SOLARIS 1
#elif defined(_AIX)
# define GTEST_OS_AIX 1
#elif defined(__hpux)
# define GTEST_OS_HPUX 1
#elif defined __native_client__
# define GTEST_OS_NACL 1
#elif defined __NetBSD__
# define GTEST_OS_NETBSD 1
#elif defined __OpenBSD__
# define GTEST_OS_OPENBSD 1
#elif defined __QNX__
# define GTEST_OS_QNX 1
#elif defined(__HAIKU__)
#define GTEST_OS_HAIKU 1
#elif defined ESP8266
#define GTEST_OS_ESP8266 1
#elif defined ESP32
#define GTEST_OS_ESP32 1
#endif // __CYGWIN__
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
File diff suppressed because it is too large. Load diff
-171
View File
@@ -1,171 +0,0 @@
// Copyright 2005, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The Google C++ Testing and Mocking Framework (Google Test)
//
// This header file declares the String class and functions used internally by
// Google Test. They are subject to change without notice. They should not used
// by code external to Google Test.
//
// This header file is #included by gtest-internal.h.
// It should not be #included by other files.
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
#ifdef __BORLANDC__
// string.h is not guaranteed to provide strcpy on C++ Builder.
# include <mem.h>
#endif
#include <string.h>
#include <string>
#include "gtest-port.h"
namespace testing {
namespace internal {
// String - an abstract class holding static string utilities.
class GTEST_API_ String {
public:
// Static utility methods
// Clones a 0-terminated C string, allocating memory using new. The
// caller is responsible for deleting the return value using
// delete[]. Returns the cloned string, or NULL if the input is
// NULL.
//
// This is different from strdup() in string.h, which allocates
// memory using malloc().
static const char* CloneCString(const char* c_str);
#if GTEST_OS_WINDOWS_MOBILE
// Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
// able to pass strings to Win32 APIs on CE we need to convert them
// to 'Unicode', UTF-16.
// Creates a UTF-16 wide string from the given ANSI string, allocating
// memory using new. The caller is responsible for deleting the return
// value using delete[]. Returns the wide string, or NULL if the
// input is NULL.
//
// The wide string is created using the ANSI codepage (CP_ACP) to
// match the behaviour of the ANSI versions of Win32 calls and the
// C runtime.
static LPCWSTR AnsiToUtf16(const char* c_str);
// Creates an ANSI string from the given wide string, allocating
// memory using new. The caller is responsible for deleting the return
// value using delete[]. Returns the ANSI string, or NULL if the
// input is NULL.
//
// The returned string is created using the ANSI codepage (CP_ACP) to
// match the behaviour of the ANSI versions of Win32 calls and the
// C runtime.
static const char* Utf16ToAnsi(LPCWSTR utf16_str);
#endif
// Compares two C strings. Returns true if and only if they have the same
// content.
//
// Unlike strcmp(), this function can handle NULL argument(s). A
// NULL C string is considered different to any non-NULL C string,
// including the empty string.
static bool CStringEquals(const char* lhs, const char* rhs);
// Converts a wide C string to a String using the UTF-8 encoding.
// NULL will be converted to "(null)". If an error occurred during
// the conversion, "(failed to convert from wide string)" is
// returned.
static std::string ShowWideCString(const wchar_t* wide_c_str);
// Compares two wide C strings. Returns true if and only if they have the
// same content.
//
// Unlike wcscmp(), this function can handle NULL argument(s). A
// NULL C string is considered different to any non-NULL C string,
// including the empty string.
static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
// Compares two C strings, ignoring case. Returns true if and only if
// they have the same content.
//
// Unlike strcasecmp(), this function can handle NULL argument(s).
// A NULL C string is considered different to any non-NULL C string,
// including the empty string.
static bool CaseInsensitiveCStringEquals(const char* lhs,
const char* rhs);
// Compares two wide C strings, ignoring case. Returns true if and only if
// they have the same content.
//
// Unlike wcscasecmp(), this function can handle NULL argument(s).
// A NULL C string is considered different to any non-NULL wide C string,
// including the empty string.
// NB: The implementations on different platforms slightly differ.
// On windows, this method uses _wcsicmp which compares according to LC_CTYPE
// environment variable. On GNU platform this method uses wcscasecmp
// which compares according to LC_CTYPE category of the current locale.
// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
// current locale.
static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
const wchar_t* rhs);
// Returns true if and only if the given string ends with the given suffix,
// ignoring case. Any string is considered to end with an empty suffix.
static bool EndsWithCaseInsensitive(
const std::string& str, const std::string& suffix);
// Formats an int value as "%02d".
static std::string FormatIntWidth2(int value); // "%02d" for width == 2
// Formats an int value as "%X".
static std::string FormatHexInt(int value);
// Formats an int value as "%X".
static std::string FormatHexUInt32(UInt32 value);
// Formats a byte as "%02X".
static std::string FormatByte(unsigned char value);
private:
String(); // Not meant to be instantiated.
}; // class String
// Gets the content of the stringstream's buffer as an std::string. Each '\0'
// character in the buffer is replaced with "\\0".
GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
} // namespace internal
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
-183
View File
@@ -1,183 +0,0 @@
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Type utilities needed for implementing typed and type-parameterized
// tests.
// GOOGLETEST_CM0001 DO NOT DELETE
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
#include "gtest-port.h"
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
// libstdc++ (which is where cxxabi.h comes from).
# if GTEST_HAS_CXXABI_H_
# include <cxxabi.h>
# elif defined(__HP_aCC)
# include <acxx_demangle.h>
# endif // GTEST_HASH_CXXABI_H_
namespace testing {
namespace internal {
// Canonicalizes a given name with respect to the Standard C++ Library.
// This handles removing the inline namespace within `std` that is
// used by various standard libraries (e.g., `std::__1`). Names outside
// of namespace std are returned unmodified.
inline std::string CanonicalizeForStdLibVersioning(std::string s) {
static const char prefix[] = "std::__";
if (s.compare(0, strlen(prefix), prefix) == 0) {
std::string::size_type end = s.find("::", strlen(prefix));
if (end != s.npos) {
// Erase everything between the initial `std` and the second `::`.
s.erase(strlen("std"), end - strlen("std"));
}
}
return s;
}
// GetTypeName<T>() returns a human-readable name of type T.
// NB: This function is also used in Google Mock, so don't move it inside of
// the typed-test-only section below.
template <typename T>
std::string GetTypeName() {
# if GTEST_HAS_RTTI
const char* const name = typeid(T).name();
# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
int status = 0;
// gcc's implementation of typeid(T).name() mangles the type name,
// so we have to demangle it.
# if GTEST_HAS_CXXABI_H_
using abi::__cxa_demangle;
# endif // GTEST_HAS_CXXABI_H_
char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
const std::string name_str(status == 0 ? readable_name : name);
free(readable_name);
return CanonicalizeForStdLibVersioning(name_str);
# else
return name;
# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
# else
return "<type>";
# endif // GTEST_HAS_RTTI
}
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
// A unique type indicating an empty node
struct None {};
# define GTEST_TEMPLATE_ template <typename T> class
// The template "selector" struct TemplateSel<Tmpl> is used to
// represent Tmpl, which must be a class template with one type
// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
// as the type Tmpl<T>. This allows us to actually instantiate the
// template "selected" by TemplateSel<Tmpl>.
//
// This trick is necessary for simulating typedef for class templates,
// which C++ doesn't support directly.
template <GTEST_TEMPLATE_ Tmpl>
struct TemplateSel {
template <typename T>
struct Bind {
typedef Tmpl<T> type;
};
};
# define GTEST_BIND_(TmplSel, T) \
TmplSel::template Bind<T>::type
template <GTEST_TEMPLATE_ Head_, GTEST_TEMPLATE_... Tail_>
struct Templates {
using Head = TemplateSel<Head_>;
using Tail = Templates<Tail_...>;
};
template <GTEST_TEMPLATE_ Head_>
struct Templates<Head_> {
using Head = TemplateSel<Head_>;
using Tail = None;
};
// Tuple-like type lists
template <typename Head_, typename... Tail_>
struct Types {
using Head = Head_;
using Tail = Types<Tail_...>;
};
template <typename Head_>
struct Types<Head_> {
using Head = Head_;
using Tail = None;
};
// Helper metafunctions to tell apart a single type from types
// generated by ::testing::Types
template <typename... Ts>
struct ProxyTypeList {
using type = Types<Ts...>;
};
template <typename>
struct is_proxy_type_list : std::false_type {};
template <typename... Ts>
struct is_proxy_type_list<ProxyTypeList<Ts...>> : std::true_type {};
// Generator which conditionally creates type lists.
// It recognizes if a requested type list should be created
// and prevents creating a new type list nested within another one.
template <typename T>
struct GenerateTypeList {
private:
using proxy = typename std::conditional<is_proxy_type_list<T>::value, T,
ProxyTypeList<T>>::type;
public:
using type = typename proxy::type;
};
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
} // namespace internal
template <typename... Ts>
using Types = internal::ProxyTypeList<Ts...>;
} // namespace testing
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
-46
View File
@@ -1,46 +0,0 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Google C++ Testing and Mocking Framework (Google Test)
//
// Sometimes it's desirable to build Google Test by compiling a single file.
// This file serves this purpose.
// This line ensures that gtest.h can be compiled on its own, even
// when it's fused.
#include "gtest/gtest.h"
#include "gtest.cc"
#include "gtest-death-test.cc"
#include "gtest-filepath.cc"
#include "gtest-matchers.cc"
#include "gtest-port.cc"
#include "gtest-printers.cc"
#include "gtest-test-part.cc"
#include "gtest-typed-test.cc"
File diff suppressed because it is too large. Load diff
-383
View File
@@ -1,383 +0,0 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "gtest/internal/gtest-filepath.h"
#include <stdlib.h>
#include "gtest/gtest-message.h"
#include "gtest/internal/gtest-port.h"
#if GTEST_OS_WINDOWS_MOBILE
# include <windows.h>
#elif GTEST_OS_WINDOWS
# include <direct.h>
# include <io.h>
#else
# include <limits.h>
# include <climits> // Some Linux distributions define PATH_MAX here.
#endif // GTEST_OS_WINDOWS_MOBILE
#include "gtest/internal/gtest-string.h"
#if GTEST_OS_WINDOWS
# define GTEST_PATH_MAX_ _MAX_PATH
#elif defined(PATH_MAX)
# define GTEST_PATH_MAX_ PATH_MAX
#elif defined(_XOPEN_PATH_MAX)
# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
#else
# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
#endif // GTEST_OS_WINDOWS
namespace testing {
namespace internal {
#if GTEST_OS_WINDOWS
// On Windows, '\\' is the standard path separator, but many tools and the
// Windows API also accept '/' as an alternate path separator. Unless otherwise
// noted, a file path can contain either kind of path separators, or a mixture
// of them.
const char kPathSeparator = '\\';
const char kAlternatePathSeparator = '/';
const char kAlternatePathSeparatorString[] = "/";
# if GTEST_OS_WINDOWS_MOBILE
// Windows CE doesn't have a current directory. You should not use
// the current directory in tests on Windows CE, but this at least
// provides a reasonable fallback.
const char kCurrentDirectoryString[] = "\\";
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
const DWORD kInvalidFileAttributes = 0xffffffff;
# else
const char kCurrentDirectoryString[] = ".\\";
# endif // GTEST_OS_WINDOWS_MOBILE
#else
const char kPathSeparator = '/';
const char kCurrentDirectoryString[] = "./";
#endif // GTEST_OS_WINDOWS
// Returns whether the given character is a valid path separator.
static bool IsPathSeparator(char c) {
#if GTEST_HAS_ALT_PATH_SEP_
return (c == kPathSeparator) || (c == kAlternatePathSeparator);
#else
return c == kPathSeparator;
#endif
}
// Returns the current working directory, or "" if unsuccessful.
FilePath FilePath::GetCurrentDir() {
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_ESP32
// These platforms do not have a current directory, so we just return
// something reasonable.
return FilePath(kCurrentDirectoryString);
#elif GTEST_OS_WINDOWS
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
#else
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
char* result = getcwd(cwd, sizeof(cwd));
# if GTEST_OS_NACL
// getcwd will likely fail in NaCl due to the sandbox, so return something
// reasonable. The user may have provided a shim implementation for getcwd,
// however, so fallback only when failure is detected.
return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
# endif // GTEST_OS_NACL
return FilePath(result == nullptr ? "" : cwd);
#endif // GTEST_OS_WINDOWS_MOBILE
}
// Returns a copy of the FilePath with the case-insensitive extension removed.
// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
// FilePath("dir/file"). If a case-insensitive extension is not
// found, returns a copy of the original FilePath.
FilePath FilePath::RemoveExtension(const char* extension) const {
const std::string dot_extension = std::string(".") + extension;
if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
return FilePath(pathname_.substr(
0, pathname_.length() - dot_extension.length()));
}
return *this;
}
// Returns a pointer to the last occurrence of a valid path separator in
// the FilePath. On Windows, for example, both '/' and '\' are valid path
// separators. Returns NULL if no path separator was found.
const char* FilePath::FindLastPathSeparator() const {
const char* const last_sep = strrchr(c_str(), kPathSeparator);
#if GTEST_HAS_ALT_PATH_SEP_
const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
// Comparing two pointers of which only one is NULL is undefined.
if (last_alt_sep != nullptr &&
(last_sep == nullptr || last_alt_sep > last_sep)) {
return last_alt_sep;
}
#endif
return last_sep;
}
// Returns a copy of the FilePath with the directory part removed.
// Example: FilePath("path/to/file").RemoveDirectoryName() returns
// FilePath("file"). If there is no directory part ("just_a_file"), it returns
// the FilePath unmodified. If there is no file part ("just_a_dir/") it
// returns an empty FilePath ("").
// On Windows platform, '\' is the path separator, otherwise it is '/'.
FilePath FilePath::RemoveDirectoryName() const {
const char* const last_sep = FindLastPathSeparator();
return last_sep ? FilePath(last_sep + 1) : *this;
}
// RemoveFileName returns the directory path with the filename removed.
// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
// On Windows platform, '\' is the path separator, otherwise it is '/'.
FilePath FilePath::RemoveFileName() const {
const char* const last_sep = FindLastPathSeparator();
std::string dir;
if (last_sep) {
dir = std::string(c_str(), static_cast<size_t>(last_sep + 1 - c_str()));
} else {
dir = kCurrentDirectoryString;
}
return FilePath(dir);
}
// Helper functions for naming files in a directory for xml output.
// Given directory = "dir", base_name = "test", number = 0,
// extension = "xml", returns "dir/test.xml". If number is greater
// than zero (e.g., 12), returns "dir/test_12.xml".
// On Windows platform, uses \ as the separator rather than /.
FilePath FilePath::MakeFileName(const FilePath& directory,
const FilePath& base_name,
int number,
const char* extension) {
std::string file;
if (number == 0) {
file = base_name.string() + "." + extension;
} else {
file = base_name.string() + "_" + StreamableToString(number)
+ "." + extension;
}
return ConcatPaths(directory, FilePath(file));
}
// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
// On Windows, uses \ as the separator rather than /.
FilePath FilePath::ConcatPaths(const FilePath& directory,
const FilePath& relative_path) {
if (directory.IsEmpty())
return relative_path;
const FilePath dir(directory.RemoveTrailingPathSeparator());
return FilePath(dir.string() + kPathSeparator + relative_path.string());
}
// Returns true if pathname describes something findable in the file-system,
// either a file, directory, or whatever.
bool FilePath::FileOrDirectoryExists() const {
#if GTEST_OS_WINDOWS_MOBILE
LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
const DWORD attributes = GetFileAttributes(unicode);
delete [] unicode;
return attributes != kInvalidFileAttributes;
#else
posix::StatStruct file_stat;
return posix::Stat(pathname_.c_str(), &file_stat) == 0;
#endif // GTEST_OS_WINDOWS_MOBILE
}
// Returns true if pathname describes a directory in the file-system
// that exists.
bool FilePath::DirectoryExists() const {
bool result = false;
#if GTEST_OS_WINDOWS
// Don't strip off trailing separator if path is a root directory on
// Windows (like "C:\\").
const FilePath& path(IsRootDirectory() ? *this :
RemoveTrailingPathSeparator());
#else
const FilePath& path(*this);
#endif
#if GTEST_OS_WINDOWS_MOBILE
LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
const DWORD attributes = GetFileAttributes(unicode);
delete [] unicode;
if ((attributes != kInvalidFileAttributes) &&
(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
result = true;
}
#else
posix::StatStruct file_stat;
result = posix::Stat(path.c_str(), &file_stat) == 0 &&
posix::IsDir(file_stat);
#endif // GTEST_OS_WINDOWS_MOBILE
return result;
}
// Returns true if pathname describes a root directory. (Windows has one
// root directory per disk drive.)
bool FilePath::IsRootDirectory() const {
#if GTEST_OS_WINDOWS
return pathname_.length() == 3 && IsAbsolutePath();
#else
return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
#endif
}
// Returns true if pathname describes an absolute path.
bool FilePath::IsAbsolutePath() const {
const char* const name = pathname_.c_str();
#if GTEST_OS_WINDOWS
return pathname_.length() >= 3 &&
((name[0] >= 'a' && name[0] <= 'z') ||
(name[0] >= 'A' && name[0] <= 'Z')) &&
name[1] == ':' &&
IsPathSeparator(name[2]);
#else
return IsPathSeparator(name[0]);
#endif
}
// Returns a pathname for a file that does not currently exist. The pathname
// will be directory/base_name.extension or
// directory/base_name_<number>.extension if directory/base_name.extension
// already exists. The number will be incremented until a pathname is found
// that does not already exist.
// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
// There could be a race condition if two or more processes are calling this
// function at the same time -- they could both pick the same filename.
FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
const FilePath& base_name,
const char* extension) {
FilePath full_pathname;
int number = 0;
do {
full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
} while (full_pathname.FileOrDirectoryExists());
return full_pathname;
}
// Returns true if FilePath ends with a path separator, which indicates that
// it is intended to represent a directory. Returns false otherwise.
// This does NOT check that a directory (or file) actually exists.
bool FilePath::IsDirectory() const {
return !pathname_.empty() &&
IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
}
// Create directories so that path exists. Returns true if successful or if
// the directories already exist; returns false if unable to create directories
// for any reason.
bool FilePath::CreateDirectoriesRecursively() const {
if (!this->IsDirectory()) {
return false;
}
if (pathname_.length() == 0 || this->DirectoryExists()) {
return true;
}
const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
return parent.CreateDirectoriesRecursively() && this->CreateFolder();
}
// Create the directory so that path exists. Returns true if successful or
// if the directory already exists; returns false if unable to create the
// directory for any reason, including if the parent directory does not
// exist. Not named "CreateDirectory" because that's a macro on Windows.
bool FilePath::CreateFolder() const {
#if GTEST_OS_WINDOWS_MOBILE
FilePath removed_sep(this->RemoveTrailingPathSeparator());
LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
delete [] unicode;
#elif GTEST_OS_WINDOWS
int result = _mkdir(pathname_.c_str());
#elif GTEST_OS_ESP8266
// do nothing
int result = 0;
#else
int result = mkdir(pathname_.c_str(), 0777);
#endif // GTEST_OS_WINDOWS_MOBILE
if (result == -1) {
return this->DirectoryExists(); // An error is OK if the directory exists.
}
return true; // No error.
}
// If input name has a trailing separator character, remove it and return the
// name, otherwise return the name string unmodified.
// On Windows platform, uses \ as the separator, other platforms use /.
FilePath FilePath::RemoveTrailingPathSeparator() const {
return IsDirectory()
? FilePath(pathname_.substr(0, pathname_.length() - 1))
: *this;
}
// Removes any redundant separators that might be in the pathname.
// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
// redundancies that might be in a pathname involving "." or "..".
void FilePath::Normalize() {
if (pathname_.c_str() == nullptr) {
pathname_ = "";
return;
}
const char* src = pathname_.c_str();
char* const dest = new char[pathname_.length() + 1];
char* dest_ptr = dest;
memset(dest_ptr, 0, pathname_.length() + 1);
while (*src != '\0') {
*dest_ptr = *src;
if (!IsPathSeparator(*src)) {
src++;
} else {
#if GTEST_HAS_ALT_PATH_SEP_
if (*dest_ptr == kAlternatePathSeparator) {
*dest_ptr = kPathSeparator;
}
#endif
while (IsPathSeparator(*src))
src++;
}
dest_ptr++;
}
*dest_ptr = '\0';
pathname_ = dest;
delete[] dest;
}
} // namespace internal
} // namespace testing
File diff suppressed because it is too large. Load diff
-97
View File
@@ -1,97 +0,0 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// The Google C++ Testing and Mocking Framework (Google Test)
//
// This file implements just enough of the matcher interface to allow
// EXPECT_DEATH and friends to accept a matcher argument.
#include "gtest/gtest-matchers.h"
#include <string>
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-port.h"
namespace testing {
// Constructs a matcher that matches a const std::string& whose value is
// equal to s.
Matcher<const std::string&>::Matcher(const std::string& s) { *this = Eq(s); }
// Constructs a matcher that matches a const std::string& whose value is
// equal to s.
Matcher<const std::string&>::Matcher(const char* s) {
*this = Eq(std::string(s));
}
// Constructs a matcher that matches a std::string whose value is equal to
// s.
Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
// Constructs a matcher that matches a std::string whose value is equal to
// s.
Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); }
#if GTEST_HAS_ABSL
// Constructs a matcher that matches a const absl::string_view& whose value is
// equal to s.
Matcher<const absl::string_view&>::Matcher(const std::string& s) {
*this = Eq(s);
}
// Constructs a matcher that matches a const absl::string_view& whose value is
// equal to s.
Matcher<const absl::string_view&>::Matcher(const char* s) {
*this = Eq(std::string(s));
}
// Constructs a matcher that matches a const absl::string_view& whose value is
// equal to s.
Matcher<const absl::string_view&>::Matcher(absl::string_view s) {
*this = Eq(std::string(s));
}
// Constructs a matcher that matches a absl::string_view whose value is equal to
// s.
Matcher<absl::string_view>::Matcher(const std::string& s) { *this = Eq(s); }
// Constructs a matcher that matches a absl::string_view whose value is equal to
// s.
Matcher<absl::string_view>::Matcher(const char* s) {
*this = Eq(std::string(s));
}
// Constructs a matcher that matches a absl::string_view whose value is equal to
// s.
Matcher<absl::string_view>::Matcher(absl::string_view s) {
*this = Eq(std::string(s));
}
#endif // GTEST_HAS_ABSL
} // namespace testing
File diff suppressed because it is too large. Load diff
-444
View File
@@ -1,444 +0,0 @@
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Google Test - The Google C++ Testing and Mocking Framework
//
// This file implements a universal value printer that can print a
// value of any type T:
//
// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
//
// It uses the << operator when possible, and prints the bytes in the
// object otherwise. A user can override its behavior for a class
// type Foo by defining either operator<<(::std::ostream&, const Foo&)
// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
// defines Foo.
#include "gtest/gtest-printers.h"
#include <stdio.h>
#include <cctype>
#include <cwchar>
#include <ostream> // NOLINT
#include <string>
#include "gtest/internal/gtest-port.h"
#include "gtest-internal-inl.h"
namespace testing {
namespace {
using ::std::ostream;
// Prints a segment of bytes in the given object.
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
size_t count, ostream* os) {
char text[5] = "";
for (size_t i = 0; i != count; i++) {
const size_t j = start + i;
if (i != 0) {
// Organizes the bytes into groups of 2 for easy parsing by
// human.
if ((j % 2) == 0)
*os << ' ';
else
*os << '-';
}
GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
*os << text;
}
}
// Prints the bytes in the given value to the given ostream.
void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
ostream* os) {
// Tells the user how big the object is.
*os << count << "-byte object <";
const size_t kThreshold = 132;
const size_t kChunkSize = 64;
// If the object size is bigger than kThreshold, we'll have to omit
// some details by printing only the first and the last kChunkSize
// bytes.
if (count < kThreshold) {
PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
} else {
PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
*os << " ... ";
// Rounds up to 2-byte boundary.
const size_t resume_pos = (count - kChunkSize + 1)/2*2;
PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
}
*os << ">";
}
} // namespace
namespace internal2 {
// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
// given object. The delegation simplifies the implementation, which
// uses the << operator and thus is easier done outside of the
// ::testing::internal namespace, which contains a << operator that
// sometimes conflicts with the one in STL.
void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
ostream* os) {
PrintBytesInObjectToImpl(obj_bytes, count, os);
}
} // namespace internal2
namespace internal {
// Depending on the value of a char (or wchar_t), we print it in one
// of three formats:
// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
// - as a hexadecimal escape sequence (e.g. '\x7F'), or
// - as a special escape sequence (e.g. '\r', '\n').
enum CharFormat {
kAsIs,
kHexEscape,
kSpecialEscape
};
// Returns true if c is a printable ASCII character. We test the
// value of c directly instead of calling isprint(), which is buggy on
// Windows Mobile.
inline bool IsPrintableAscii(wchar_t c) {
return 0x20 <= c && c <= 0x7E;
}
// Prints a wide or narrow char c as a character literal without the
// quotes, escaping it when necessary; returns how c was formatted.
// The template argument UnsignedChar is the unsigned version of Char,
// which is the type of c.
template <typename UnsignedChar, typename Char>
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
wchar_t w_c = static_cast<wchar_t>(c);
switch (w_c) {
case L'\0':
*os << "\\0";
break;
case L'\'':
*os << "\\'";
break;
case L'\\':
*os << "\\\\";
break;
case L'\a':
*os << "\\a";
break;
case L'\b':
*os << "\\b";
break;
case L'\f':
*os << "\\f";
break;
case L'\n':
*os << "\\n";
break;
case L'\r':
*os << "\\r";
break;
case L'\t':
*os << "\\t";
break;
case L'\v':
*os << "\\v";
break;
default:
if (IsPrintableAscii(w_c)) {
*os << static_cast<char>(c);
return kAsIs;
} else {
ostream::fmtflags flags = os->flags();
*os << "\\x" << std::hex << std::uppercase
<< static_cast<int>(static_cast<UnsignedChar>(c));
os->flags(flags);
return kHexEscape;
}
}
return kSpecialEscape;
}
// Prints a wchar_t c as if it's part of a string literal, escaping it when
// necessary; returns how c was formatted.
static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
switch (c) {
case L'\'':
*os << "'";
return kAsIs;
case L'"':
*os << "\\\"";
return kSpecialEscape;
default:
return PrintAsCharLiteralTo<wchar_t>(c, os);
}
}
// Prints a char c as if it's part of a string literal, escaping it when
// necessary; returns how c was formatted.
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
return PrintAsStringLiteralTo(
static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
}
// Prints a wide or narrow character c and its code. '\0' is printed
// as "'\\0'", other unprintable characters are also properly escaped
// using the standard C++ escape sequence. The template argument
// UnsignedChar is the unsigned version of Char, which is the type of c.
template <typename UnsignedChar, typename Char>
void PrintCharAndCodeTo(Char c, ostream* os) {
// First, print c as a literal in the most readable form we can find.
*os << ((sizeof(c) > 1) ? "L'" : "'");
const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
*os << "'";
// To aid user debugging, we also print c's code in decimal, unless
// it's 0 (in which case c was printed as '\\0', making the code
// obvious).
if (c == 0)
return;
*os << " (" << static_cast<int>(c);
// For more convenience, we print c's code again in hexadecimal,
// unless c was already printed in the form '\x##' or the code is in
// [1, 9].
if (format == kHexEscape || (1 <= c && c <= 9)) {
// Do nothing.
} else {
*os << ", 0x" << String::FormatHexInt(static_cast<int>(c));
}
*os << ")";
}
void PrintTo(unsigned char c, ::std::ostream* os) {
PrintCharAndCodeTo<unsigned char>(c, os);
}
void PrintTo(signed char c, ::std::ostream* os) {
PrintCharAndCodeTo<unsigned char>(c, os);
}
// Prints a wchar_t as a symbol if it is printable or as its internal
// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
void PrintTo(wchar_t wc, ostream* os) {
PrintCharAndCodeTo<wchar_t>(wc, os);
}
// Prints the given array of characters to the ostream. CharType must be either
// char or wchar_t.
// The array starts at begin, the length is len, it may include '\0' characters
// and may not be NUL-terminated.
template <typename CharType>
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static CharFormat PrintCharsAsStringTo(
const CharType* begin, size_t len, ostream* os) {
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
*os << kQuoteBegin;
bool is_previous_hex = false;
CharFormat print_format = kAsIs;
for (size_t index = 0; index < len; ++index) {
const CharType cur = begin[index];
if (is_previous_hex && IsXDigit(cur)) {
// Previous character is of '\x..' form and this character can be
// interpreted as another hexadecimal digit in its number. Break string to
// disambiguate.
*os << "\" " << kQuoteBegin;
}
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
// Remember if any characters required hex escaping.
if (is_previous_hex) {
print_format = kHexEscape;
}
}
*os << "\"";
return print_format;
}
// Prints a (const) char/wchar_t array of 'len' elements, starting at address
// 'begin'. CharType must be either char or wchar_t.
template <typename CharType>
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static void UniversalPrintCharArray(
const CharType* begin, size_t len, ostream* os) {
// The code
// const char kFoo[] = "foo";
// generates an array of 4, not 3, elements, with the last one being '\0'.
//
// Therefore when printing a char array, we don't print the last element if
// it's '\0', such that the output matches the string literal as it's
// written in the source code.
if (len > 0 && begin[len - 1] == '\0') {
PrintCharsAsStringTo(begin, len - 1, os);
return;
}
// If, however, the last element in the array is not '\0', e.g.
// const char kFoo[] = { 'f', 'o', 'o' };
// we must print the entire array. We also print a message to indicate
// that the array is not NUL-terminated.
PrintCharsAsStringTo(begin, len, os);
*os << " (no terminating NUL)";
}
// Prints a (const) char array of 'len' elements, starting at address 'begin'.
void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
UniversalPrintCharArray(begin, len, os);
}
// Prints a (const) wchar_t array of 'len' elements, starting at address
// 'begin'.
void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
UniversalPrintCharArray(begin, len, os);
}
// Prints the given C string to the ostream.
void PrintTo(const char* s, ostream* os) {
if (s == nullptr) {
*os << "NULL";
} else {
*os << ImplicitCast_<const void*>(s) << " pointing to ";
PrintCharsAsStringTo(s, strlen(s), os);
}
}
// MSVC compiler can be configured to define whar_t as a typedef
// of unsigned short. Defining an overload for const wchar_t* in that case
// would cause pointers to unsigned shorts be printed as wide strings,
// possibly accessing more memory than intended and causing invalid
// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
// wchar_t is implemented as a native type.
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
// Prints the given wide C string to the ostream.
void PrintTo(const wchar_t* s, ostream* os) {
if (s == nullptr) {
*os << "NULL";
} else {
*os << ImplicitCast_<const void*>(s) << " pointing to ";
PrintCharsAsStringTo(s, wcslen(s), os);
}
}
#endif // wchar_t is native
namespace {
bool ContainsUnprintableControlCodes(const char* str, size_t length) {
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
for (size_t i = 0; i < length; i++) {
unsigned char ch = *s++;
if (std::iscntrl(ch)) {
switch (ch) {
case '\t':
case '\n':
case '\r':
break;
default:
return true;
}
}
}
return false;
}
bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
bool IsValidUTF8(const char* str, size_t length) {
const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
for (size_t i = 0; i < length;) {
unsigned char lead = s[i++];
if (lead <= 0x7f) {
continue; // single-byte character (ASCII) 0..7F
}
if (lead < 0xc2) {
return false; // trail byte or non-shortest form
} else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
++i; // 2-byte character
} else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
IsUTF8TrailByte(s[i]) &&
IsUTF8TrailByte(s[i + 1]) &&
// check for non-shortest form and surrogate
(lead != 0xe0 || s[i] >= 0xa0) &&
(lead != 0xed || s[i] < 0xa0)) {
i += 2; // 3-byte character
} else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
IsUTF8TrailByte(s[i]) &&
IsUTF8TrailByte(s[i + 1]) &&
IsUTF8TrailByte(s[i + 2]) &&
// check for non-shortest form
(lead != 0xf0 || s[i] >= 0x90) &&
(lead != 0xf4 || s[i] < 0x90)) {
i += 3; // 4-byte character
} else {
return false;
}
}
return true;
}
void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
if (!ContainsUnprintableControlCodes(str, length) &&
IsValidUTF8(str, length)) {
*os << "\n As Text: \"" << str << "\"";
}
}
} // anonymous namespace
void PrintStringTo(const ::std::string& s, ostream* os) {
if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
if (GTEST_FLAG(print_utf8)) {
ConditionalPrintAsText(s.data(), s.size(), os);
}
}
}
#if GTEST_HAS_STD_WSTRING
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os);
}
#endif // GTEST_HAS_STD_WSTRING
} // namespace internal
} // namespace testing
-108
View File
@@ -1,108 +0,0 @@
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The Google C++ Testing and Mocking Framework (Google Test)
#include "gtest/gtest-test-part.h"
#include "gtest/internal/gtest-port.h"
#include "gtest-internal-inl.h"
namespace testing {
using internal::GetUnitTestImpl;
// Gets the summary of the failure message by omitting the stack trace
// in it.
std::string TestPartResult::ExtractSummary(const char* message) {
const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
return stack_trace == nullptr ? message : std::string(message, stack_trace);
}
// Prints a TestPartResult object.
std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
return os << internal::FormatFileLocation(result.file_name(),
result.line_number())
<< " "
<< (result.type() == TestPartResult::kSuccess
? "Success"
: result.type() == TestPartResult::kSkip
? "Skipped"
: result.type() == TestPartResult::kFatalFailure
? "Fatal failure"
: "Non-fatal failure")
<< ":\n"
<< result.message() << std::endl;
}
// Appends a TestPartResult to the array.
void TestPartResultArray::Append(const TestPartResult& result) {
array_.push_back(result);
}
// Returns the TestPartResult at the given index (0-based).
const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
if (index < 0 || index >= size()) {
printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
internal::posix::Abort();
}
return array_[static_cast<size_t>(index)];
}
// Returns the number of TestPartResult objects in the array.
int TestPartResultArray::size() const {
return static_cast<int>(array_.size());
}
namespace internal {
HasNewFatalFailureHelper::HasNewFatalFailureHelper()
: has_new_fatal_failure_(false),
original_reporter_(GetUnitTestImpl()->
GetTestPartResultReporterForCurrentThread()) {
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
}
HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
original_reporter_);
}
void HasNewFatalFailureHelper::ReportTestPartResult(
const TestPartResult& result) {
if (result.fatally_failed())
has_new_fatal_failure_ = true;
original_reporter_->ReportTestPartResult(result);
}
} // namespace internal
} // namespace testing
-118
View File
@@ -1,118 +0,0 @@
// Copyright 2008 Google Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "gtest/gtest-typed-test.h"
#include "gtest/gtest.h"
namespace testing {
namespace internal {
#if GTEST_HAS_TYPED_TEST_P
// Skips to the first non-space char in str. Returns an empty string if str
// contains only whitespace characters.
static const char* SkipSpaces(const char* str) {
while (IsSpace(*str))
str++;
return str;
}
static std::vector<std::string> SplitIntoTestNames(const char* src) {
std::vector<std::string> name_vec;
src = SkipSpaces(src);
for (; src != nullptr; src = SkipComma(src)) {
name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src)));
}
return name_vec;
}
// Verifies that registered_tests match the test names in
// registered_tests_; returns registered_tests if successful, or
// aborts the program otherwise.
const char* TypedTestSuitePState::VerifyRegisteredTestNames(
const char* file, int line, const char* registered_tests) {
typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
registered_ = true;
std::vector<std::string> name_vec = SplitIntoTestNames(registered_tests);
Message errors;
std::set<std::string> tests;
for (std::vector<std::string>::const_iterator name_it = name_vec.begin();
name_it != name_vec.end(); ++name_it) {
const std::string& name = *name_it;
if (tests.count(name) != 0) {
errors << "Test " << name << " is listed more than once.\n";
continue;
}
bool found = false;
for (RegisteredTestIter it = registered_tests_.begin();
it != registered_tests_.end();
++it) {
if (name == it->first) {
found = true;
break;
}
}
if (found) {
tests.insert(name);
} else {
errors << "No test named " << name
<< " can be found in this test suite.\n";
}
}
for (RegisteredTestIter it = registered_tests_.begin();
it != registered_tests_.end();
++it) {
if (tests.count(it->first) == 0) {
errors << "You forgot to list test " << it->first << ".\n";
}
}
const std::string& errors_str = errors.GetString();
if (errors_str != "") {
fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
errors_str.c_str());
fflush(stderr);
posix::Abort();
}
return registered_tests;
}
#endif // GTEST_HAS_TYPED_TEST_P
} // namespace internal
} // namespace testing
File diff suppressed because it is too large. Load diff
-55
View File
@@ -1,55 +0,0 @@
// Copyright 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstdio>
#include "gtest/gtest.h"
#if GTEST_OS_ESP8266 || GTEST_OS_ESP32
#if GTEST_OS_ESP8266
extern "C" {
#endif
void setup() {
testing::InitGoogleTest();
}
void loop() { RUN_ALL_TESTS(); }
#if GTEST_OS_ESP8266
}
#endif
#else
GTEST_API_ int main(int argc, char **argv) {
printf("Running main() from %s\n", __FILE__);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
#endif
+25 -8
View File
@@ -59,7 +59,8 @@ struct ImGui_ImplDX11_Data
ID3D11PixelShader* pPixelShader;
ID3D11SamplerState* pFontSampler;
ID3D11SamplerState* pTextureSampler;
ID3D11ShaderResourceView* pFontTextureView;
ID3D11SamplerState* pPointSampler;
ImTextureDX11 FontTexture;
ID3D11RasterizerState* pRasterizerState;
ID3D11BlendState* pBlendState;
ID3D11DepthStencilState* pDepthStencilState;
@@ -279,11 +280,17 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ctx->RSSetScissorRects(1, &r);
// Bind texture, Draw
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
if (pcmd->TextureId != (ImTextureID)bd->pFontTextureView)
ctx->PSSetSamplers(0, 1, &bd->pTextureSampler);
ImTextureDX11 *tex = (ImTextureDX11 *)pcmd->GetTexID();
if (tex != &bd->FontTexture)
{
if (tex->pointSampling)
ctx->PSSetSamplers(0, 1, &bd->pPointSampler);
else
ctx->PSSetSamplers(0, 1, &bd->pTextureSampler);
}
else
ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
ID3D11ShaderResourceView* texture_srv = tex->shaderResourceView;
ctx->PSSetShaderResources(0, 1, &texture_srv);
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
}
@@ -350,12 +357,12 @@ static void ImGui_ImplDX11_CreateFontsTexture()
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView);
bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->FontTexture.shaderResourceView);
pTexture->Release();
}
// Store our identifier
io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
io.Fonts->SetTexID((ImTextureID)&bd->FontTexture);
// Create texture samplers
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
@@ -375,6 +382,9 @@ static void ImGui_ImplDX11_CreateFontsTexture()
desc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
desc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER;
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTextureSampler);
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
bd->pd3dDevice->CreateSamplerState(&desc, &bd->pPointSampler);
}
}
@@ -540,7 +550,13 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
if (bd->pTextureSampler) { bd->pTextureSampler->Release(); bd->pTextureSampler = nullptr; }
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (bd->pPointSampler) { bd->pPointSampler->Release(); bd->pPointSampler = nullptr; }
if (bd->FontTexture.shaderResourceView) {
bd->FontTexture.shaderResourceView->Release();
bd->FontTexture.shaderResourceView = nullptr;
// We copied data->FontTexture.shaderResourceView to io.Fonts->TexID so let's clear that as well.
ImGui::GetIO().Fonts->SetTexID(0);
}
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
@@ -555,6 +571,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
@@ -603,7 +620,7 @@ void ImGui_ImplDX11_Shutdown()
void ImGui_ImplDX11_NewFrame()
{
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX11_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX11_Init()?");
if (!bd->pFontSampler)
ImGui_ImplDX11_CreateDeviceObjects();
@@ -19,6 +19,7 @@
struct ID3D11Device;
struct ID3D11DeviceContext;
struct ID3D11ShaderResourceView;
IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
@@ -29,4 +30,11 @@ IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
// ImTextureID should be a pointer to this struct
struct ImTextureDX11
{
ID3D11ShaderResourceView *shaderResourceView;
bool pointSampling;
};
#endif // #ifndef IMGUI_DISABLE
+31 -11
View File
@@ -48,7 +48,7 @@ struct ImGui_ImplDX9_Data
LPDIRECT3DDEVICE9 pd3dDevice;
LPDIRECT3DVERTEXBUFFER9 pVB;
LPDIRECT3DINDEXBUFFER9 pIB;
LPDIRECT3DTEXTURE9 FontTexture;
ImTextureDX9 FontTexture;
int VertexBufferSize;
int IndexBufferSize;
@@ -244,17 +244,30 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
// Apply Scissor/clipping rectangle, Bind texture, Draw
const RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID();
const ImTextureDX9 *tex = (const ImTextureDX9 *)pcmd->GetTexID();
const LPDIRECT3DTEXTURE9 texture = tex->d3dTexture;
bd->pd3dDevice->SetTexture(0, texture);
if (texture != bd->FontTexture)
if (tex != &bd->FontTexture)
{
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
if (tex->pointSampling)
{
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
}
else
{
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}
}
else
{
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}
bd->pd3dDevice->SetScissorRect(&r);
bd->pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
@@ -268,6 +281,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
@@ -338,18 +352,18 @@ static bool ImGui_ImplDX9_CreateFontsTexture()
#endif
// Upload texture to graphics system
bd->FontTexture = nullptr;
if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, rgba_support ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, nullptr) < 0)
bd->FontTexture.d3dTexture = nullptr;
if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, rgba_support ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture.d3dTexture, nullptr) < 0)
return false;
D3DLOCKED_RECT tex_locked_rect;
if (bd->FontTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK)
if (bd->FontTexture.d3dTexture->LockRect(0, &tex_locked_rect, nullptr, 0) != D3D_OK)
return false;
for (int y = 0; y < height; y++)
memcpy((unsigned char*)tex_locked_rect.pBits + (size_t)tex_locked_rect.Pitch * y, pixels + (size_t)width * bytes_per_pixel * y, (size_t)width * bytes_per_pixel);
bd->FontTexture->UnlockRect(0);
bd->FontTexture.d3dTexture->UnlockRect(0);
// Store our identifier
io.Fonts->SetTexID((ImTextureID)bd->FontTexture);
io.Fonts->SetTexID((ImTextureID)&bd->FontTexture);
#ifndef IMGUI_USE_BGRA_PACKED_COLOR
if (!rgba_support && io.Fonts->TexPixelsUseColors)
@@ -376,15 +390,21 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
return;
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
if (bd->FontTexture) { bd->FontTexture->Release(); bd->FontTexture = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (bd->FontTexture.d3dTexture)
{
bd->FontTexture.d3dTexture->Release();
bd->FontTexture.d3dTexture = nullptr;
// We copied bd->FontTexture to io.Fonts->TexID so let's clear that as well.
ImGui::GetIO().Fonts->SetTexID(0);
}
}
void ImGui_ImplDX9_NewFrame()
{
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX9_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX9_Init()?");
if (!bd->FontTexture)
if (!bd->FontTexture.d3dTexture)
ImGui_ImplDX9_CreateDeviceObjects();
}
@@ -18,6 +18,7 @@
#ifndef IMGUI_DISABLE
struct IDirect3DDevice9;
struct IDirect3DTexture9;
IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device);
IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown();
@@ -28,4 +29,11 @@ IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
// ImTextureID should be a pointer to this struct
struct ImTextureDX9
{
IDirect3DTexture9 *d3dTexture;
bool pointSampling;
};
#endif // #ifndef IMGUI_DISABLE
@@ -66,9 +66,7 @@
#include "TargetConditionals.h"
#endif
#include "wsi/gl_context.h"
#include "rend/gles/glcache.h"
#include "hw/pvr/Renderer_if.h"
// OpenGL Data
static char g_GlslVersionString[32] = "";
@@ -81,11 +79,12 @@ static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
// Functions
static bool ImGui_ImplOpenGL3_CreateDeviceObjects();
static void ImGui_ImplOpenGL3_DestroyDeviceObjects();
static void ImGui_ImplOpenGL3_DrawBackground();
bool ImGui_ImplOpenGL3_Init()
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
io.BackendRendererName = "imgui_impl_opengl3";
// Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
@@ -114,7 +113,6 @@ void ImGui_ImplOpenGL3_NewFrame()
{
if (!g_FontTexture)
ImGui_ImplOpenGL3_CreateDeviceObjects();
ImGui_ImplOpenGL3_DrawBackground();
}
// OpenGL3 Render function.
@@ -224,7 +222,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
glcache.Scissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT)
// Bind texture, Draw
glcache.BindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
glcache.BindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)));
}
}
@@ -257,7 +255,7 @@ static bool ImGui_ImplOpenGL3_CreateFontsTexture()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Store our identifier
io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture;
io.Fonts->SetTexID((ImTextureID)g_FontTexture);
return true;
}
@@ -268,7 +266,6 @@ static void ImGui_ImplOpenGL3_DestroyFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
glcache.DeleteTextures(1, &g_FontTexture);
io.Fonts->TexID = 0;
g_FontTexture = 0;
}
}
@@ -489,15 +486,3 @@ static void ImGui_ImplOpenGL3_DestroyDeviceObjects()
ImGui_ImplOpenGL3_DestroyFontsTexture();
}
static void ImGui_ImplOpenGL3_DrawBackground()
{
#ifndef TARGET_IPHONE
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
glcache.Disable(GL_SCISSOR_TEST);
glcache.ClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
if (renderer != nullptr)
renderer->RenderLastFrame();
}
+16 -14
View File
@@ -33,6 +33,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().)
// 2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering.
// 2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure.
// 2024-01-19: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236)
@@ -41,14 +42,14 @@
// 2024-01-03: Vulkan: Stopped creating command pools with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT as we don't reset them.
// 2023-11-29: Vulkan: Fixed mismatching allocator passed to vkCreateCommandPool() vs vkDestroyCommandPool(). (#7075)
// 2023-11-10: *BREAKING CHANGE*: Removed parameter from ImGui_ImplVulkan_CreateFontsTexture(): backend now creates its own command-buffer to upload fonts.
// *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unecessary as we create and destroy those objects in the backend.
// *BREAKING CHANGE*: Removed ImGui_ImplVulkan_DestroyFontUploadObjects() which is now unnecessary as we create and destroy those objects in the backend.
// ImGui_ImplVulkan_CreateFontsTexture() is automatically called by NewFrame() the first time.
// You can call ImGui_ImplVulkan_CreateFontsTexture() again to recreate the font atlas texture.
// Added ImGui_ImplVulkan_DestroyFontsTexture() but you probably never need to call this.
// 2023-07-04: Vulkan: Added optional support for VK_KHR_dynamic_rendering. User needs to set init_info->UseDynamicRendering = true and init_info->ColorAttachmentFormat.
// 2023-01-02: Vulkan: Fixed sampler passed to ImGui_ImplVulkan_AddTexture() not being honored + removed a bunch of duplicate code.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2022-10-04: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symetry. (#914, #5738).
// 2022-10-04: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symmetry. (#914, #5738).
// 2022-01-20: Vulkan: Added support for ImTextureID as VkDescriptorSet. User need to call ImGui_ImplVulkan_AddTexture(). Building for 32-bit targets requires '#define ImTextureID ImU64'. (#914).
// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
@@ -108,12 +109,13 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi
// Vulkan prototypes for use with custom loaders
// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h
#ifdef VK_NO_PROTOTYPES
#if defined(VK_NO_PROTOTYPES) && !defined(VOLK_H_)
#define IMGUI_IMPL_VULKAN_USE_LOADER
static bool g_FunctionsLoaded = false;
#else
static bool g_FunctionsLoaded = true;
#endif
#ifdef VK_NO_PROTOTYPES
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
#define IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_MAP_MACRO) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \
@@ -184,7 +186,7 @@ static bool g_FunctionsLoaded = true;
#define IMGUI_VULKAN_FUNC_DEF(func) static PFN_##func func;
IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF)
#undef IMGUI_VULKAN_FUNC_DEF
#endif // VK_NO_PROTOTYPES
#endif // IMGUI_IMPL_VULKAN_USE_LOADER
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
static PFN_vkCmdBeginRenderingKHR ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR;
@@ -584,14 +586,14 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
// Bind DescriptorSet with font or user texture
VkDescriptorSet desc_set[1] = { (VkDescriptorSet)pcmd->TextureId };
VkDescriptorSet desc_set = (VkDescriptorSet)pcmd->GetTexID();
if (sizeof(ImTextureID) < sizeof(ImU64))
{
// We don't support texture switches if ImTextureID hasn't been redefined to be 64-bit. Do a flaky check that other textures haven't been used.
IM_ASSERT(pcmd->TextureId == (ImTextureID)bd->FontDescriptorSet);
desc_set[0] = bd->FontDescriptorSet;
IM_ASSERT(pcmd->GetTexID() == (ImTextureID)bd->FontDescriptorSet);
desc_set = bd->FontDescriptorSet;
}
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, nullptr);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, &desc_set, 0, nullptr);
// Draw
vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
@@ -818,7 +820,6 @@ void ImGui_ImplVulkan_DestroyFontsTexture()
{
ImGui_ImplVulkan_RemoveTexture(bd->FontDescriptorSet);
bd->FontDescriptorSet = VK_NULL_HANDLE;
io.Fonts->SetTexID(0);
}
if (bd->FontView) { vkDestroyImageView(v->Device, bd->FontView, v->Allocator); bd->FontView = VK_NULL_HANDLE; }
@@ -1048,8 +1049,8 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch
// Load function pointers
// You can use the default Vulkan loader using:
// ImGui_ImplVulkan_LoadFunctions([](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); });
// But this would be equivalent to not setting VK_NO_PROTOTYPES.
#ifdef VK_NO_PROTOTYPES
// But this would be roughly equivalent to not setting VK_NO_PROTOTYPES.
#ifdef IMGUI_IMPL_VULKAN_USE_LOADER
#define IMGUI_VULKAN_FUNC_LOAD(func) \
func = reinterpret_cast<decltype(func)>(loader_func(#func, user_data)); \
if (func == nullptr) \
@@ -1078,7 +1079,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
if (info->UseDynamicRendering)
{
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
#ifndef VK_NO_PROTOTYPES
#ifndef IMGUI_IMPL_VULKAN_USE_LOADER
ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(vkGetInstanceProcAddr(info->Instance, "vkCmdBeginRenderingKHR"));
ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(vkGetInstanceProcAddr(info->Instance, "vkCmdEndRenderingKHR"));
#endif
@@ -1090,6 +1091,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
}
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
// Setup backend capabilities flags
@@ -1131,7 +1133,7 @@ void ImGui_ImplVulkan_Shutdown()
void ImGui_ImplVulkan_NewFrame()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplVulkan_Init()?");
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplVulkan_Init()?");
if (!bd->FontDescriptorSet)
ImGui_ImplVulkan_CreateFontsTexture();
Loaded 100 of 955 files, more files were not shown because too many files have changed in this diff. Show more