395 Commits
Author SHA1 Message Date
Flyinghead 5f4eefab58 naomi: add pjustic (rev b) and pjustica. fix gunsur2 and gunsur2j
Issue #716
2025-05-06 20:04:11 +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 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
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
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
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
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 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
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
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
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
519 changed files with 92100 additions and 19815 deletions

No files matched your search

+1 -1
View File
@@ -12,7 +12,7 @@ assignees: ''
Platform / OS / Hardware:
Github hash:
Flycast version:
Hardware:
+21 -9
View File
@@ -4,6 +4,7 @@ on: [push, pull_request]
jobs:
build:
name: Android
runs-on: ubuntu-latest
steps:
@@ -16,7 +17,7 @@ jobs:
with:
fetch-depth: 0
submodules: recursive
- uses: actions/setup-java@v4
with:
java-version: '17'
@@ -28,6 +29,10 @@ jobs:
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]
@@ -37,19 +42,15 @@ jobs:
- name: Gradle
working-directory: shell/android-studio
run: ./gradlew bundleRelease --parallel
run: ./gradlew assembleRelease bundleRelease --parallel
env:
SENTRY_UPLOAD_URL: ${{ secrets.SENTRY_UPLOAD_URL }}
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
- name: Upload to Google Play
uses: r0adkll/[email protected]
- uses: actions/upload-artifact@v4
with:
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
packageName: com.flycast.emulator
releaseFiles: shell/android-studio/flycast/build/outputs/bundle/release/flycast-release.aab
track: internal
status: draft
name: flycast-release.apk
path: shell/android-studio/flycast/build/outputs/apk/release/flycast-release.apk
- name: Build dump_syms
working-directory: core/deps/breakpad
@@ -69,6 +70,17 @@ jobs:
mv libflycast.so.sym symbols/libflycast.so/$BUILD_ID
done
- name: Setup Rclone
uses: AnimMouse/setup-rclone@v1
with:
rclone_config: ${{ secrets.RCLONE_CONFIG }}
- name: Upload to S3
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
env:
+48
View File
@@ -0,0 +1,48 @@
name: BSD CI
on: [push, pull_request]
jobs:
build:
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
runs-on: ubuntu-latest
strategy:
matrix:
operating_system: [ freebsd, netbsd, openbsd ]
architecture: [ arm64, x86-64 ]
include:
- operating_system: freebsd
version: '14.2'
pkginstall: 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: '10.1'
pkginstall: sudo pkgin update && sudo pkgin -y install alsa-lib ccache cmake gcc12 git libao libzip lua54 miniupnpc ninja-build pkgconf pulseaudio SDL2 libcdio && export PATH=/usr/pkg/gcc12/bin:$PATH
- operating_system: openbsd
version: '7.6'
pkginstall: sudo pkg_add ccache cmake git libao libzip miniupnpc ninja pkgconf pulseaudio sdl2 libcdio
exclude:
- architecture: arm64
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- uses: actions/cache@v4
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/[email protected]
with:
operating_system: ${{ matrix.operating_system }}
architecture: ${{ matrix.architecture }}
version: ${{ matrix.version }}
environment_variables: CCACHE_DIR
run: |
${{ matrix.pkginstall }}
cmake -B build -DUSE_LIBCDIO=ON -DCMAKE_BUILD_TYPE=Release -G Ninja
cmake --build build --config Release
+180
View File
@@ -0,0 +1,180 @@
name: C/C++ CI
on: [push, pull_request]
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
defaults:
run:
shell: ${{ matrix.config.shell }}
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache
strategy:
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 -DUSE_DISCORD=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-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: |
# 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 pulseaudio
brew uninstall --ignore-dependencies zstd
VULKAN_VER=1.3.261.1 && 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
echo "VULKAN_SDK=$HOME/VulkanSDK/macOS" >> $GITHUB_ENV
if: runner.os == 'macOS'
- name: Set up build environment (Linux)
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 libcdio-dev libfuse2
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
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 mingw-w64-x86_64-libcdio
if: matrix.config.shell == 'msys2 {0}'
- name: Set up build environment (Windows, Visual Studio)
run: |
choco install ccache directx-sdk ninja
echo DXSDK_DIR=C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)>> %GITHUB_ENV%
if: matrix.config.shell == 'cmd'
- uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.config.arch }}
if: matrix.config.shell == 'cmd'
- uses: actions/checkout@v4
with:
fetch-depth: 0
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
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
with:
path: ${{ env.CCACHE_DIR }}
key: ccache-${{ matrix.config.name }}-${{ github.sha }}
restore-keys: ccache-${{ matrix.config.name }}-
if: runner.os != 'macOS'
- name: CMake
run: |
cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.buildType }} -DCMAKE_INSTALL_PREFIX=artifact ${{ matrix.config.cmakeArgs }} -DSENTRY_UPLOAD_URL=${{ env.SENTRY_UPLOAD_URL }}
cmake --build build --config ${{ matrix.config.buildType }} --target install
env:
SENTRY_UPLOAD_URL: ${{ secrets.SENTRY_UPLOAD_URL }}
- name: Unit Tests
run: |
cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.buildType }} -DCMAKE_INSTALL_PREFIX=artifact -DENABLE_CTEST=ON ${{ matrix.config.cmakeArgs }}
cmake --build build --config ${{ matrix.config.buildType }}
./build/flycast
if: matrix.config.name == 'x86_64-pc-linux-gnu'
- name: Dump symbols
run: |
mkdir -p symbols
core/deps/breakpad/bin/dump_syms artifact/bin/flycast.exe > symbols/flycast.sym 2>/dev/null
strip artifact/bin/flycast.exe
if: matrix.config.name == 'x86_64-w64-mingw32'
- name: Build breakpad (linux)
working-directory: core/deps/breakpad
run: |
./configure
make
sudo make install
if: matrix.config.name == 'x86_64-pc-linux-gnu'
- name: Dump symbols and make AppImage (linux)
run: |
mkdir -p symbols
dump_syms artifact/bin/flycast > symbols/flycast.sym 2>/dev/null
strip artifact/bin/flycast
shell/linux/make-appimage.sh . artifact/bin appimage
mv flycast-x86_64.AppImage artifact/bin
rm artifact/bin/flycast
if: matrix.config.name == 'x86_64-pc-linux-gnu'
- uses: actions/upload-artifact@v4
with:
name: flycast-${{ matrix.config.name }}
path: |
artifact/bin
artifact/lib/libretro
- name: Package app (macos)
run: |
cd artifact/bin
zip -rm flycast.app.zip Flycast.app
if: matrix.config.name == 'apple-darwin'
- name: Package app (windows)
run: |
powershell Compress-Archive artifact/bin/flycast.exe artifact/bin/flycast.zip
rm artifact/bin/flycast.exe
if: matrix.config.name == 'x86_64-w64-mingw32'
- name: Setup Rclone
uses: AnimMouse/setup-rclone@v1
with:
rclone_config: ${{ secrets.RCLONE_CONFIG }}
- name: Upload to S3
run: rclone copy artifact/bin scaleway:flycast-builds/${{ matrix.config.destDir }}/${GITHUB_REF#refs/}-$GITHUB_SHA
shell: bash
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push' && matrix.config.destDir != ''
- name: Setup Sentry CLI
uses: mathieu-bour/setup-sentry-cli@v2
env:
SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
with:
url: https://sentry.io
token: ${{ env.SENTRY_TOKEN }}
organization: flycast
project: minidump
version: 2.21.2
if: ${{ env.SENTRY_TOKEN != '' }}
- name: Upload symbols to Sentry (Windows, macOS, Linux)
run: |
VERSION=$(git describe --tags --always)
sentry-cli releases new "$VERSION"
sentry-cli releases set-commits "$VERSION" --auto
sentry-cli debug-files upload symbols
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') }}
+36
View File
@@ -0,0 +1,36 @@
# Prepare source texts & upload them to Crowdin
name: Crowdin Source Texts Upload
# on change to the English texts
on:
push:
branches:
- master
paths:
- 'shell/libretro/libretro_core_options.h'
jobs:
upload_source_file:
runs-on: ubuntu-latest
steps:
- name: Setup Java JDK
uses: actions/setup-java@v4
with:
java-version: 18
distribution: zulu
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Checkout
uses: actions/checkout@v4
- name: Upload Source
shell: bash
env:
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
run: |
python3 intl/upload_workflow.py $CROWDIN_API_KEY "flyinghead-flycast" "shell/libretro/libretro_core_options.h"
+49
View File
@@ -0,0 +1,49 @@
# Download translations form Crowdin & Recreate libretro_core_options_intl.h
name: Crowdin Translation Integration
on:
schedule:
# please choose a random time & weekday to avoid all repos synching at the same time
- cron: '15 22 * * 5' # Fridays at 10:15 PM, UTC
jobs:
create_intl_file:
runs-on: ubuntu-latest
steps:
- name: Setup Java JDK
uses: actions/setup-java@v4
with:
java-version: 18
distribution: zulu
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Checkout
uses: actions/checkout@v4
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.
- name: Create intl file
shell: bash
env:
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
run: |
python3 intl/download_workflow.py $CROWDIN_API_KEY "flyinghead-flycast" "shell/libretro/libretro_core_options_intl.h"
- name: Commit files
run: |
git config --local user.email "[email protected]"
git config --local user.name "github-actions[bot]"
git add intl/*_workflow.py "shell/libretro/libretro_core_options_intl.h"
git commit -m "Fetch translations & Recreate libretro_core_options_intl.h"
- name: GitHub Push
uses: ad-m/[email protected]
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
+59
View File
@@ -0,0 +1,59 @@
name: Nintendo Switch CI
on: [push, pull_request]
jobs:
build:
name: Switch ${{ matrix.config.name }}
runs-on: ubuntu-latest
container: devkitpro/devkita64:latest
strategy:
matrix:
config:
- {name: standalone, destDir: switch}
- {name: libretro, cmakeArgs: -DLIBRETRO=ON}
steps:
- name: Set up build environment
run: |
sudo apt-get update
sudo apt-get -y install ccache
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Mark git repository as safe
run: git config --global --add safe.directory $PWD
- uses: actions/cache@v4
with:
path: ~/.ccache
key: ccache-switch-${{ matrix.config.name }}-${{ github.sha }}
restore-keys: ccache-switch-${{ matrix.config.name }}-
- name: CMake
run: |
$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
with:
name: flycast-switch-${{ matrix.config.name }}
path: artifact/bin
- name: Package app
run: zip -m artifact/bin/flycast.nro.zip artifact/bin/flycast.nro
if: hashFiles('artifact/bin/flycast.nro') != ''
- name: Setup Rclone
uses: AnimMouse/setup-rclone@v1
with:
rclone_config: ${{ secrets.RCLONE_CONFIG }}
version: v1.69.1
- name: Upload to S3
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 != ''
+51
View File
@@ -0,0 +1,51 @@
name: Windows UWP CI
on: [push, pull_request]
jobs:
build:
name: UWP
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- 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 --build build --config Release -- /m
shell: cmd
- uses: ilammy/msvc-dev-cmd@v1
- name: Package app
run: |
mkdir build\artifact
cd build\AppPackages\flycast\flycast_*_x64_Test
mkdir tmp
ren *.msix flycast.msix
makeappx.exe unpack /p .\flycast.msix /d tmp
copy ..\..\..\Release\*.dll tmp
makeappx pack /d tmp /p ..\..\..\artifact\flycast.appx
- name: Sign app
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
with:
name: flycast-uwp
path: build/artifact
- name: Setup Rclone
uses: AnimMouse/setup-rclone@v1
with:
rclone_config: ${{ secrets.RCLONE_CONFIG }}
- name: Upload to S3
run: rclone copy build/artifact scaleway:flycast-builds/xbox/${GITHUB_REF#refs/}-$GITHUB_SHA
shell: bash
if: github.repository == 'flyinghead/flycast' && github.event_name == 'push'
+3
View File
@@ -17,3 +17,6 @@ cmake-build-*/
# Dependencies from .gitmodules
core/deps/breakpad/
core/deps/glslang/
.cache/
compile_commands.json
CMakeUserPresets.json
+5 -3
View File
@@ -9,12 +9,12 @@
variables:
GIT_SUBMODULE_STRATEGY: recursive
CORENAME: flycast
CORE_ARGS: -DLIBRETRO=ON -DCMAKE_BUILD_TYPE=Release
CORE_ARGS: -DLIBRETRO=ON -DUSE_LIBCDIO=ON -DCMAKE_BUILD_TYPE=Release
.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 -DCMAKE_BUILD_TYPE=Release
.core-defs-osx-x64:
extends: .core-defs
@@ -36,7 +36,7 @@
.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
- cmake -DLIBRETRO=ON -DCMAKE_BUILD_TYPE=Release -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
- 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
@@ -120,6 +120,8 @@ 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:
+5 -2
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
@@ -31,7 +31,7 @@
url = https://github.com/vkedwardli/Spout2.git
[submodule "core/deps/discord-rpc"]
path = core/deps/discord-rpc
url = https://github.com/flyinghead/discord-rpc
url = https://github.com/harmonytf/discord-rpc
[submodule "core/deps/libadrenotools"]
path = core/deps/libadrenotools
url = https://github.com/bylaws/libadrenotools
@@ -41,3 +41,6 @@
[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
+163 -82
View File
@@ -18,9 +18,10 @@ if(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0" CACHE STRING "Minimum tvOS deployment version")
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "")
else()
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.11" CACHE STRING "Minimum macOS deployment version")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13" CACHE STRING "Minimum macOS deployment version")
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "")
endif()
set(ZLIB_LIBRARY "-lz" CACHE STRING "Use generic linker flag for Xcode to support multiple SDKs")
endif()
if(LIBRETRO)
@@ -58,6 +59,7 @@ option(USE_GLES2 "Use GLES2 API" OFF)
option(USE_HOST_GLSLANG "Use host glslang" OFF)
option(USE_HOST_LIBZIP "Use host libzip" ON)
option(USE_HOST_SDL "Use host SDL library" ${USE_HOST_SDL_DEFAULT})
option(USE_HOST_LIBCHDR "Use host libchdr" OFF)
option(USE_OPENMP "Use OpenMP if available" ON)
option(USE_VULKAN "Build with Vulkan support" ON)
option(USE_DX9 "Build with Direct3D 9 support" ON)
@@ -65,11 +67,17 @@ option(USE_DX11 "Build with Direct3D 11 support" ON)
option(LIBRETRO "Build libretro core" OFF)
option(USE_OPENGL "Use OpenGL API" ON)
option(USE_VIDEOCORE "RPI: use the legacy Broadcom GLES libraries" OFF)
option(APPLE_BREAKPAD "macOS: Build breakpad client and dump symbols" OFF)
option(USE_ALSA "Build with ALSA support" ON)
option(USE_LIBAO "Build with AO support" ON)
option(USE_OSS "Build with OSS support" OFF)
option(USE_PULSEAUDIO "Build with PulseAudio support" ON)
option(USE_BREAKPAD "Build and link with breakpad library" ON)
option(USE_LUA "Build with Lua support" ON)
option(ENABLE_GDB_SERVER "Build with GDB debugging support" OFF)
option(ENABLE_DC_PROFILER "Build with support for target machine (SH4) profiler" OFF)
option(ENABLE_FC_PROFILER "Build with support for host app (Flycast) profiler" OFF)
option(USE_DISCORD "Use Discord Presence API" OFF)
option(USE_LIBCDIO "Use libcdio for CDROM access" OFF)
if(IOS AND NOT LIBRETRO)
set(USE_VULKAN OFF CACHE BOOL "Force vulkan off" FORCE)
@@ -139,6 +147,13 @@ if(NINTENDO_SWITCH)
if(USE_GLES)
target_compile_definitions(${PROJECT_NAME} PRIVATE GLES)
endif()
# asio
target_compile_definitions(${PROJECT_NAME} PRIVATE
ASIO_DISABLE_LOCAL_SOCKETS
ASIO_DISABLE_SERIAL_PORT
ESHUTDOWN=110
SA_RESTART=0
SA_NOCLDWAIT=0)
elseif(LIBRETRO)
add_library(${PROJECT_NAME} SHARED core/emulator.cpp)
@@ -212,6 +227,10 @@ else()
add_executable(${PROJECT_NAME} core/emulator.cpp)
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES
CMAKE_CXX_STANDARD 20
CMAKE_CXX_STANDARD_REQUIRED ON)
if(WINDOWS_STORE)
set(USE_OPENGL OFF)
set(USE_VULKAN OFF)
@@ -229,7 +248,7 @@ else()
$<$<COMPILE_LANGUAGE:CXX>:-Wall>)
endif()
if(${CMAKE_OSX_SYSROOT} MATCHES "\/MacOSX.platform\/Developer\/SDKs")
if(APPLE AND NOT IOS)
set(TARGET_MAC ON)
endif()
@@ -247,6 +266,7 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE
$<$<BOOL:${MSVC}>:NOMINMAX>
$<$<BOOL:${TEST_AUTOMATION}>:TEST_AUTOMATION>
$<$<BOOL:${WINDOWS_STORE}>:NOCRYPT>
$<$<BOOL:${WINDOWS_STORE}>:_WIN32_WINNT=0x0A00>
$<$<OR:$<BOOL:${MINGW}>,$<BOOL:${MSVC}>>:_USE_MATH_DEFINES>)
if(UNIX AND NOT ANDROID AND NOT APPLE)
@@ -258,7 +278,7 @@ if(NOT "${SENTRY_UPLOAD_URL}" STREQUAL "")
target_compile_definitions(${PROJECT_NAME} PRIVATE SENTRY_UPLOAD="${SENTRY_UPLOAD_URL}")
endif()
target_include_directories(${PROJECT_NAME} PRIVATE core core/deps core/deps/stb core/deps/json)
target_include_directories(${PROJECT_NAME} PRIVATE core core/deps core/deps/stb core/deps/json core/deps/asio/asio/include)
if(LIBRETRO)
target_include_directories(${PROJECT_NAME} PRIVATE shell/libretro)
endif()
@@ -266,7 +286,7 @@ if(NINTENDO_SWITCH)
target_include_directories(${PROJECT_NAME} PRIVATE shell/switch)
endif()
if(NOT LIBRETRO)
if(USE_BREAKPAD AND NOT LIBRETRO)
find_program(SH_EXECUTABLE sh)
if((ANDROID AND NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") OR (MINGW AND SH_EXECUTABLE) OR (CMAKE_SYSTEM_NAME STREQUAL "Linux"))
add_subdirectory(core/deps/breakpad)
@@ -275,7 +295,7 @@ if(NOT LIBRETRO)
endif()
target_link_libraries(${PROJECT_NAME} PUBLIC breakpad_client)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_BREAKPAD)
elseif(APPLE AND NOT IOS AND APPLE_BREAKPAD)
elseif(APPLE AND NOT IOS)
target_sources(${PROJECT_NAME} PRIVATE
core/deps/breakpad/src/client/minidump_file_writer-inl.h
core/deps/breakpad/src/client/minidump_file_writer.cc
@@ -327,26 +347,26 @@ if(NOT LIBRETRO)
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build/breakpad/dump_syms
-a x86_64
-g ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/Flycast.app.dSYM
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/Flycast.app/Contents/MacOS/Flycast > ../symbols/Flycast-x64.sym
$<TARGET_FILE:flycast> > ../symbols/Flycast-x64.sym
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build/breakpad/dump_syms
-a arm64
-g ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/Flycast.app.dSYM
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/Flycast.app/Contents/MacOS/Flycast > ../symbols/Flycast-arm64.sym
$<TARGET_FILE:flycast> > ../symbols/Flycast-arm64.sym
)
else()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND sleep 20
COMMAND mkdir -p ../symbols
COMMAND dsymutil ${CMAKE_CURRENT_BINARY_DIR}/Flycast.app/Contents/MacOS/Flycast
COMMAND dsymutil $<TARGET_FILE:flycast>
-o ${CMAKE_CURRENT_BINARY_DIR}/Flycast.app.dSYM
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build/breakpad/dump_syms
-a x86_64
-g ${CMAKE_CURRENT_BINARY_DIR}/Flycast.app.dSYM
${CMAKE_CURRENT_BINARY_DIR}/Flycast.app/Contents/MacOS/Flycast > ../symbols/Flycast-x64.sym
$<TARGET_FILE:flycast> > ../symbols/Flycast-x64.sym
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build/breakpad/dump_syms
-a arm64
-g ${CMAKE_CURRENT_BINARY_DIR}/Flycast.app.dSYM
${CMAKE_CURRENT_BINARY_DIR}/Flycast.app/Contents/MacOS/Flycast > ../symbols/Flycast-arm64.sym
$<TARGET_FILE:flycast> > ../symbols/Flycast-arm64.sym
)
endif()
endif()
@@ -356,7 +376,8 @@ if(USE_OPENMP)
find_package(OpenMP)
if(OpenMP_CXX_FOUND)
if(MINGW)
target_link_libraries(${PROJECT_NAME} PRIVATE "-static -lgomp -lpthread")
target_link_libraries(${PROJECT_NAME} PRIVATE -lpthread)
target_link_options(${PROJECT_NAME} PRIVATE -fopenmp -static)
target_compile_options(${PROJECT_NAME} PRIVATE -fopenmp)
elseif(ANDROID)
# Reference: https://android.googlesource.com/platform/ndk/+/refs/heads/master/tests/device/openmp/CMakeLists.txt
@@ -376,7 +397,7 @@ if(USE_OPENMP)
message("-- Found OpenMP.xcframework: ${OPENMP_FRAMEWORK} (Linking static library before CMake support linking xcframework)")
target_link_libraries(${PROJECT_NAME} PRIVATE ${OPENMP_FRAMEWORK})
target_include_directories(${PROJECT_NAME} PRIVATE ${OPENMP_XCFRAMEWORK}/ios-arm64_arm64e/OpenMP.framework/Versions/A/Headers)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xclang -fopenmp")
target_compile_options(${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Xclang -fopenmp>)
endif()
else()
message("-- Could NOT find OpenMP.xcframework, compile it using shell/apple/emulator-ios/OpenMP/build_ios_openmp.sh")
@@ -411,11 +432,17 @@ if(USE_VULKAN)
endif()
if(NOT LIBRETRO)
find_package(ALSA)
if(ALSA_FOUND AND NOT ANDROID)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_ALSA)
target_include_directories(${PROJECT_NAME} PRIVATE ${ALSA_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE ${ALSA_LIBRARIES})
if(USE_OSS)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_OSS)
endif()
if(USE_ALSA)
find_package(ALSA)
if(ALSA_FOUND AND NOT ANDROID)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_ALSA)
target_include_directories(${PROJECT_NAME} PRIVATE ${ALSA_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE ${ALSA_LIBRARIES})
endif()
endif()
if(MINGW)
@@ -448,7 +475,18 @@ if(NOT LIBRETRO)
endif()
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_SDL USE_SDL_AUDIO)
target_sources(${PROJECT_NAME} PRIVATE core/sdl/sdl.cpp core/sdl/sdl.h core/sdl/sdl_gamepad.h core/sdl/sdl_keyboard.h)
target_sources(${PROJECT_NAME} PRIVATE
core/sdl/sdl.cpp
core/sdl/sdl.h
core/sdl/sdl_gamepad.h
core/sdl/sdl_keyboard.h
core/sdl/sdl_keyboard_mac.h
core/sdl/dreamlink.cpp
core/sdl/dreamlink.h
core/sdl/dreampicoport.cpp
core/sdl/dreampicoport.h
core/sdl/dreamconn.cpp
core/sdl/dreamconn.h)
if((UNIX AND NOT APPLE) OR NINTENDO_SWITCH)
find_package(CURL REQUIRED)
@@ -462,37 +500,52 @@ if(NOT LIBRETRO)
target_link_libraries(${PROJECT_NAME} PRIVATE ZLIB::ZLIB)
endif()
find_package(Lua 5.2)
if(NOT APPLE AND LUA_FOUND)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_LUA)
target_include_directories(${PROJECT_NAME} PRIVATE ${LUA_INCLUDE_DIR} core/deps/luabridge/Source)
list(TRANSFORM LUA_LIBRARIES REPLACE "\.dll" "")
target_link_libraries(${PROJECT_NAME} PRIVATE ${LUA_LIBRARIES})
if(USE_LUA)
find_package(Lua 5.2)
if(NOT APPLE AND LUA_FOUND)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_LUA)
target_include_directories(${PROJECT_NAME} PRIVATE ${LUA_INCLUDE_DIR} core/deps/luabridge/Source)
list(TRANSFORM LUA_LIBRARIES REPLACE "\.dll" "")
target_link_libraries(${PROJECT_NAME} PRIVATE ${LUA_LIBRARIES})
endif()
endif()
endif()
add_subdirectory(core/deps/libchdr EXCLUDE_FROM_ALL)
target_link_libraries(${PROJECT_NAME} PRIVATE chdr-static)
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/libchdr/include)
find_package(PkgConfig)
if(NOT WITH_SYSTEM_ZLIB)
set(ZLIB_RELATIVE_PATH "core/deps/libchdr/deps/zlib-1.3.1")
target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/${ZLIB_RELATIVE_PATH}" "${CMAKE_CURRENT_BINARY_DIR}/${ZLIB_RELATIVE_PATH}")
option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" OFF)
add_subdirectory("core/deps/libchdr/deps/zlib-1.3.1" EXCLUDE_FROM_ALL)
set_target_properties(zlibstatic PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(${PROJECT_NAME} PRIVATE zlibstatic)
# help libzip find the package
set(ZLIB_FOUND TRUE)
set(ZLIB_RELATIVE_PATH "core/deps/libchdr/deps/zlib-1.3.1")
set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${ZLIB_RELATIVE_PATH}" "${CMAKE_CURRENT_BINARY_DIR}/${ZLIB_RELATIVE_PATH}")
cmake_policy(SET CMP0026 OLD)
get_target_property(ZLIB_LIBRARY_RELEASE zlibstatic LOCATION)
get_target_property(ZLIB_LIBRARY_DEBUG zlibstatic LOCATION_Debug)
endif()
find_package(PkgConfig)
if(PKG_CONFIG_FOUND AND USE_HOST_LIBCHDR)
pkg_check_modules(LIBCHDR IMPORTED_TARGET libchdr)
target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::LIBCHDR)
else()
option(ZSTD_BUILD_SHARED "BUILD SHARED LIBRARIES" OFF)
option(ZSTD_BUILD_PROGRAMS "BUILD PROGRAMS" OFF)
option(ZSTD_LEGACY_SUPPORT "LEGACY SUPPORT" OFF)
add_subdirectory(core/deps/libchdr/deps/zstd-1.5.6/build/cmake EXCLUDE_FROM_ALL)
target_link_libraries(${PROJECT_NAME} PRIVATE libzstd_static)
option(WITH_SYSTEM_ZSTD "Use system provided zstd library" ON)
add_subdirectory(core/deps/libchdr EXCLUDE_FROM_ALL)
target_link_libraries(${PROJECT_NAME} PRIVATE chdr-static)
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/libchdr/include)
endif()
if(PKG_CONFIG_FOUND AND NOT ANDROID AND NOT APPLE AND NOT LIBRETRO)
pkg_check_modules(AO IMPORTED_TARGET ao)
if(AO_FOUND)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_LIBAO)
target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::AO)
if(USE_LIBAO)
pkg_check_modules(AO IMPORTED_TARGET ao)
if(AO_FOUND)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_LIBAO)
target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::AO)
endif()
endif()
if(NOT SDL2_FOUND)
@@ -509,10 +562,12 @@ if(PKG_CONFIG_FOUND AND NOT ANDROID AND NOT APPLE AND NOT LIBRETRO)
endif()
endif()
pkg_check_modules(LIBPULSE IMPORTED_TARGET libpulse)
if(LIBPULSE_FOUND)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_PULSEAUDIO)
target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::LIBPULSE)
if(USE_PULSEAUDIO)
pkg_check_modules(LIBPULSE IMPORTED_TARGET libpulse)
if(LIBPULSE_FOUND)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_PULSEAUDIO)
target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::LIBPULSE)
endif()
endif()
if(USE_HOST_LIBZIP)
@@ -627,10 +682,6 @@ if(NOT MINIUPNP_FOUND)
endif()
if(NOT LIBZIP_FOUND OR NINTENDO_SWITCH)
cmake_policy(SET CMP0026 OLD)
set(zstd_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/core/deps/libchdr/deps/zstd-1.5.6/lib")
get_target_property(zstd_STATIC_LIBRARY libzstd_static LOCATION)
option(ENABLE_COMMONCRYPTO "Enable use of CommonCrypto" OFF)
option(ENABLE_GNUTLS "Enable use of GnuTLS" OFF)
option(ENABLE_MBEDTLS "Enable use of mbed TLS" OFF)
@@ -645,10 +696,32 @@ if(NOT LIBZIP_FOUND OR NINTENDO_SWITCH)
option(BUILD_DOC "Build documentation" OFF)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
option(LIBZIP_DO_INSTALL "Install libzip and the related files" OFF)
add_subdirectory(core/deps/libzip)
add_subdirectory(core/deps/libzip EXCLUDE_FROM_ALL)
target_link_libraries(${PROJECT_NAME} PRIVATE libzip::zip)
endif()
if(USE_LIBCDIO)
if(PKG_CONFIG_FOUND)
pkg_check_modules(CDIO IMPORTED_TARGET libcdio)
if(CDIO_FOUND)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_LIBCDIO)
if(MINGW)
# Force static link
target_link_libraries(${PROJECT_NAME} PRIVATE "-l:libcdio.a -l:libiconv.a -lwinmm")
else()
target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::CDIO)
endif()
endif()
endif()
if(NOT CDIO_FOUND)
find_package(libcdio)
if(TARGET libcdio::libcdio)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_LIBCDIO)
target_link_libraries(${PROJECT_NAME} PRIVATE libcdio::libcdio)
endif()
endif()
endif()
if(WIN32)
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/dirent)
endif()
@@ -742,7 +815,7 @@ target_sources(${PROJECT_NAME} PRIVATE core/deps/md5/md5.cpp)
if(USE_DISCORD AND NOT LIBRETRO)
option(BUILD_EXAMPLES "Build example apps" OFF)
add_subdirectory(core/deps/discord-rpc)
add_subdirectory(core/deps/discord-rpc EXCLUDE_FROM_ALL)
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/discord-rpc/include)
target_link_libraries(${PROJECT_NAME} PRIVATE discord-rpc)
target_compile_definitions(${PROJECT_NAME} PRIVATE USE_DISCORD)
@@ -791,6 +864,9 @@ if(LIBRETRO)
if(APPLE)
target_sources(${PROJECT_NAME} PRIVATE shell/libretro/oslib_apple.mm)
endif()
if(WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE mswsock)
endif()
endif()
target_sources(${PROJECT_NAME} PRIVATE
@@ -1029,22 +1105,23 @@ if(NOT LIBRETRO)
fonts/Roboto-Medium.ttf.zip
fonts/Roboto-Regular.ttf.zip
fonts/fa-solid-900.ttf.zip)
if(ANDROID)
if(ANDROID OR IOS)
cmrc_add_resources(flycast-resources
WHENCE resources
resources/picture/buttons.png)
resources/picture/buttons.png
resources/picture/buttons-arcade.png)
endif()
endif()
target_sources(${PROJECT_NAME} PRIVATE
core/imgread/cdi.cpp
core/imgread/cdio.cpp
core/imgread/chd.cpp
core/imgread/common.cpp
core/imgread/common.h
core/imgread/cue.cpp
core/imgread/gdi.cpp
core/imgread/ImgReader.cpp
core/imgread/ioctl.cpp
core/imgread/iso9660.h
core/imgread/isofs.cpp
core/imgread/isofs.h)
@@ -1125,7 +1202,11 @@ target_sources(${PROJECT_NAME} PRIVATE
core/network/output.cpp
core/network/output.h
core/network/picoppp.cpp
core/network/picoppp.h)
core/network/picoppp.h
core/network/netservice.cpp
core/network/netservice.h
core/network/dcnet.cpp
core/network/dcnet.h)
if(ANDROID)
target_sources(${PROJECT_NAME} PRIVATE
@@ -1301,6 +1382,8 @@ target_sources(${PROJECT_NAME} PRIVATE
core/rend/tileclip.h
core/rend/TexCache.cpp
core/rend/TexCache.h
core/rend/texconv.cpp
core/rend/texconv.h
core/rend/norend/norend.cpp)
if(NOT LIBRETRO)
target_sources(${PROJECT_NAME} PRIVATE
@@ -1310,8 +1393,8 @@ if(NOT LIBRETRO)
core/ui/gui.cpp
core/ui/gui.h
core/ui/gui_achievements.cpp
core/ui/gui_android.cpp
core/ui/gui_android.h
core/ui/vgamepad.cpp
core/ui/vgamepad.h
core/ui/gui_chat.h
core/ui/gui_cheats.cpp
core/ui/gui_util.cpp
@@ -1327,7 +1410,7 @@ if(NOT LIBRETRO)
endif()
if(USE_VULKAN)
target_compile_definitions(${PROJECT_NAME} PUBLIC VK_NO_PROTOTYPES)
target_compile_definitions(${PROJECT_NAME} PUBLIC VK_ENABLE_BETA_EXTENSIONS VK_NO_PROTOTYPES)
if(ANDROID)
target_compile_definitions(${PROJECT_NAME} PUBLIC VK_USE_PLATFORM_ANDROID_KHR)
elseif(X11_FOUND)
@@ -1335,7 +1418,6 @@ if(USE_VULKAN)
elseif(WIN32)
target_compile_definitions(${PROJECT_NAME} PUBLIC VK_USE_PLATFORM_WIN32_KHR)
elseif(APPLE)
target_compile_definitions(${PROJECT_NAME} PUBLIC VK_USE_PLATFORM_MACOS_MVK)
target_compile_definitions(${PROJECT_NAME} PUBLIC VK_USE_PLATFORM_METAL_EXT)
endif()
@@ -1343,7 +1425,6 @@ if(USE_VULKAN)
target_link_libraries(${PROJECT_NAME} PRIVATE Vulkan::Headers)
add_subdirectory(core/deps/VulkanMemoryAllocator)
target_compile_definitions(VulkanMemoryAllocator INTERFACE $<$<BOOL:${APPLE}>:VMA_USE_STL_SHARED_MUTEX=0>) # Only available on macOS 10.12+
target_compile_options(VulkanMemoryAllocator INTERFACE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:AppleClang,Clang>>:-Wno-nullability-completeness>)
target_link_libraries(${PROJECT_NAME} PRIVATE GPUOpen::VulkanMemoryAllocator)
@@ -1619,6 +1700,10 @@ if(NOT LIBRETRO)
target_sources(${PROJECT_NAME} PRIVATE
shell/android-studio/flycast/src/main/jni/src/Android.cpp
shell/android-studio/flycast/src/main/jni/src/android_gamepad.h
shell/android-studio/flycast/src/main/jni/src/android_storage.h
shell/android-studio/flycast/src/main/jni/src/http_client.h
shell/android-studio/flycast/src/main/jni/src/jni_util.h
shell/android-studio/flycast/src/main/jni/src/android_input.cpp
shell/android-studio/flycast/src/main/jni/src/android_keyboard.h)
target_link_libraries(${PROJECT_NAME} PRIVATE android log)
@@ -1643,13 +1728,15 @@ if(NOT LIBRETRO)
shell/apple/emulator-ios/emulator/FlycastViewController.mm
shell/apple/emulator-ios/emulator/PadViewController.h
shell/apple/emulator-ios/emulator/PadViewController.mm
shell/apple/emulator-ios/emulator/EditPadViewController.h
shell/apple/emulator-ios/emulator/EditPadViewController.mm
shell/apple/emulator-ios/emulator/EmulatorView.h
shell/apple/emulator-ios/emulator/EmulatorView.mm
shell/apple/emulator-ios/emulator/main.m
shell/apple/emulator-ios/emulator/iCade-iOS/iCadeReaderView.h
shell/apple/emulator-ios/emulator/iCade-iOS/iCadeReaderView.m
shell/apple/emulator-ios/emulator/iCade-iOS/iCadeState.h)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc -fmodules")
target_compile_options(${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-fobjc-arc -fmodules>)
set_source_files_properties(shell/apple/emulator-ios/emulator/FlycastViewController.mm PROPERTIES COMPILE_OPTIONS -fcxx-modules)
set_source_files_properties(shell/apple/emulator-ios/emulator/iCade-iOS/iCadeReaderView.m PROPERTIES COMPILE_OPTIONS -fno-objc-arc)
@@ -1657,7 +1744,8 @@ if(NOT LIBRETRO)
shell/apple/emulator-ios/emulator/Images.xcassets
shell/apple/emulator-ios/emulator/FlycastStoryboard.storyboard
shell/apple/emulator-ios/emulator/LaunchScreen.storyboard
shell/apple/emulator-ios/emulator/PadViewController.xib)
shell/apple/emulator-ios/emulator/PadViewController.xib
shell/apple/emulator-ios/emulator/EditPadViewController.xib)
target_sources(${PROJECT_NAME} PRIVATE ${IOS_RESOURCES})
source_group("Resources" FILES ${IOS_RESOURCES})
set_source_files_properties(${IOS_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
@@ -1715,15 +1803,9 @@ if(NOT LIBRETRO)
add_subdirectory(core/deps/Syphon)
target_link_libraries(${PROJECT_NAME} PRIVATE Syphon)
if(${CMAKE_GENERATOR} MATCHES "^Xcode.*")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${SYPHON_METALLIB}
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/Flycast.app/Contents/Resources/)
else()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${SYPHON_METALLIB}
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/Flycast.app/Contents/Resources/)
endif()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${SYPHON_METALLIB}
$<TARGET_FILE_DIR:flycast>/../Resources/)
target_compile_definitions(${PROJECT_NAME} PRIVATE VIDEO_ROUTING)
target_sources(${PROJECT_NAME} PRIVATE
@@ -1774,15 +1856,9 @@ if(NOT LIBRETRO)
${IOSURFACE_LIBRARY}
${MULTITOUCH_SUPPORT_LIBRARY})
if(${CMAKE_GENERATOR} MATCHES "^Xcode.*")
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "$ENV{VULKAN_SDK}/lib/libMoltenVK.dylib"
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/Flycast.app/Contents/Frameworks/libvulkan.dylib)
else()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "$ENV{VULKAN_SDK}/lib/libMoltenVK.dylib"
${CMAKE_CURRENT_BINARY_DIR}/Flycast.app/Contents/Frameworks/libvulkan.dylib)
endif()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "$ENV{VULKAN_SDK}/lib/libMoltenVK.dylib"
$<TARGET_FILE_DIR:flycast>/../Frameworks/libvulkan.dylib)
endif()
elseif(UNIX)
if(NOT BUILD_TESTING)
@@ -1831,7 +1907,7 @@ if(NOT LIBRETRO)
endif()
target_sources(${PROJECT_NAME} PRIVATE shell/windows/flycast.rc)
target_link_libraries(${PROJECT_NAME} PRIVATE dsound winmm ws2_32 wsock32 xinput9_1_0 cfgmgr32 wininet)
target_link_libraries(${PROJECT_NAME} PRIVATE dsound winmm ws2_32 wsock32 xinput9_1_0 cfgmgr32 wininet psapi)
endif()
endif()
endif()
@@ -1843,7 +1919,7 @@ if(BUILD_TESTING)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
endif()
add_subdirectory(core/deps/googletest EXCLUDE_FROM_ALL)
target_link_libraries(${PROJECT_NAME} PRIVATE gtest_main)
target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest_main)
target_sources(${PROJECT_NAME} PRIVATE
tests/src/CheatManagerTest.cpp
@@ -1853,7 +1929,10 @@ if(BUILD_TESTING)
tests/src/serialize_test.cpp
tests/src/AicaArmTest.cpp
tests/src/Sh4InterpreterTest.cpp
tests/src/MmuTest.cpp)
tests/src/MmuTest.cpp
tests/src/util/PeriodicThreadTest.cpp
tests/src/util/TsQueueTest.cpp
tests/src/util/WorkerThreadTest.cpp)
endif()
if(NINTENDO_SWITCH)
@@ -1878,6 +1957,8 @@ if(IOS)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>-${CMAKE_OSX_SYSROOT}/Flycast.ipa" TYPE BIN)
elseif(NINTENDO_SWITCH AND NOT LIBRETRO)
install(FILES ${CMAKE_BINARY_DIR}/flycast.nro DESTINATION "${CMAKE_INSTALL_BINDIR}")
elseif(LIBRETRO)
install(TARGETS ${PROJECT_NAME} DESTINATION "${CMAKE_INSTALL_LIBDIR}/libretro")
else()
install(TARGETS ${PROJECT_NAME} DESTINATION "${CMAKE_INSTALL_BINDIR}")
endif()
+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"
}
}
]
}
+3 -1
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/).
+103 -120
View File
@@ -37,8 +37,9 @@
#include <atomic>
#include <utility>
#include <xxhash.h>
#include <thread>
#include <functional>
#include "util/worker_thread.h"
#include "util/periodic_thread.h"
namespace achievements
{
@@ -74,10 +75,8 @@ private:
std::string getOrDownloadImage(const char *url);
std::pair<std::string, bool> getCachedImage(const char *url);
void diskChange();
void asyncTask(std::function<void()> f);
void startThread();
void stopThread();
void backgroundThread();
void asyncTask(std::function<void()>&& f);
void stopThreads();
static void clientLoginWithTokenCallback(int result, const char *error_message, rc_client_t *client, void *userdata);
static void clientLoginWithPasswordCallback(int result, const char *error_message, rc_client_t *client, void *userdata);
@@ -112,11 +111,12 @@ private:
std::string cachePath;
std::unordered_map<u64, std::string> cacheMap;
std::mutex cacheMutex;
std::vector<std::function<void()>> tasks;
std::mutex taskMutex;
std::thread taskThread;
cResetEvent resetEvent;
bool threadRunning = false;
WorkerThread taskThread {"RA-background"};
PeriodicThread idleThread { "RA-idle", [this]() {
if (active)
rc_client_idle(rc_client);
}};
};
bool init() {
@@ -176,6 +176,7 @@ Achievements::Achievements()
EventManager::listen(Event::Pause, emuEventCallback, this);
EventManager::listen(Event::Resume, emuEventCallback, this);
EventManager::listen(Event::DiskChange, emuEventCallback, this);
idleThread.setPeriod(1000);
}
Achievements::~Achievements()
@@ -188,44 +189,13 @@ Achievements::~Achievements()
term();
}
void Achievements::asyncTask(std::function<void()> f)
{
{
std::lock_guard<std::mutex> _(taskMutex);
tasks.emplace_back(f);
}
resetEvent.Set();
void Achievements::asyncTask(std::function<void()>&& f) {
taskThread.run(std::move(f));
}
void Achievements::startThread()
{
threadRunning = true;
taskThread = std::thread(&Achievements::backgroundThread, this);
}
void Achievements::stopThread()
{
threadRunning = false;
resetEvent.Set();
if (taskThread.joinable())
taskThread.join();
}
void Achievements::backgroundThread()
{
ThreadName _("RA-background");
while (threadRunning)
{
if (!resetEvent.Wait(1000) && active && paused)
rc_client_idle(rc_client);
std::vector<std::function<void()>> localTasks;
{
std::lock_guard<std::mutex> _(taskMutex);
std::swap(tasks, localTasks);
}
for (auto& f : localTasks)
f();
}
void Achievements::stopThreads() {
taskThread.stop();
idleThread.stop();
}
bool Achievements::init()
@@ -243,7 +213,6 @@ bool Achievements::init()
//rc_client_set_unofficial_enabled(rc_client, 0);
//rc_client_set_spectator_mode_enabled(rc_client, 0);
loadCache();
startThread();
if (!config::AchievementsUserName.get().empty() && !config::AchievementsToken.get().empty())
{
@@ -301,7 +270,7 @@ void Achievements::loadCache()
}
static u64 hashUrl(const char *url) {
return XXH64(url, strlen(url), 13);
return XXH3_64bits(url, strlen(url));
}
std::pair<std::string, bool> Achievements::getCachedImage(const char *url)
@@ -357,7 +326,7 @@ void Achievements::term()
if (rc_client == nullptr)
return;
unloadGame();
stopThread();
stopThreads();
rc_client_destroy(rc_client);
rc_client = nullptr;
}
@@ -365,16 +334,16 @@ void Achievements::term()
void Achievements::authenticationSuccess(const rc_client_user_t *user)
{
NOTICE_LOG(COMMON, "RA Login successful");
asyncTask([this, user]() {
char url[512];
int rc = rc_client_user_get_image_url(user, url, sizeof(url));
if (rc == RC_OK)
{
std::string image = getOrDownloadImage(url);
std::string url(512, '\0');
int rc = rc_client_user_get_image_url(user, url.data(), url.size());
if (rc == RC_OK)
{
asyncTask([this, url]() {
std::string image = getOrDownloadImage(url.c_str());
std::string text = "User " + config::AchievementsUserName.get() + " authenticated";
notifier.notify(Notification::Login, image, text);
}
});
});
}
loggedOn = true;
if (!settings.content.fileName.empty()) // TODO better test?
loadGame();
@@ -600,46 +569,48 @@ void Achievements::handleUnlockEvent(const rc_client_event_t *event)
assert(cheevo != nullptr);
INFO_LOG(COMMON, "RA: Achievement %s (%u) for game %s unlocked", cheevo->title, cheevo->id, settings.content.title.c_str());
asyncTask([this, cheevo]() {
char url[512];
int rc = rc_client_achievement_get_image_url(cheevo, cheevo->state, url, sizeof(url));
if (rc == RC_OK)
{
std::string image = getOrDownloadImage(url);
std::string text = "Achievement " + std::string(cheevo->title) + " unlocked!";
notifier.notify(Notification::Login, image, text, cheevo->description);
}
});
std::string title(cheevo->title);
std::string description(cheevo->description);
std::string url(512, '\0');
int rc = rc_client_achievement_get_image_url(cheevo, cheevo->state, url.data(), url.size());
if (rc == RC_OK)
{
asyncTask([this, url, title, description]() {
std::string image = getOrDownloadImage(url.c_str());
std::string text = "Achievement " + title + " unlocked!";
notifier.notify(Notification::Login, image, text, description);
});
}
}
void Achievements::handleAchievementChallengeIndicatorShowEvent(const rc_client_event_t *event)
{
const rc_client_achievement_t* cheevo = event->achievement;
INFO_LOG(COMMON, "RA: Challenge: %s", cheevo->title);
asyncTask([this, cheevo]() {
char url[128];
int rc = rc_client_achievement_get_image_url(cheevo, RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED, url, sizeof(url));
if (rc == RC_OK)
{
std::string image = getOrDownloadImage(url);
std::string url(512, '\0');
int rc = rc_client_achievement_get_image_url(cheevo, RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED, url.data(), url.size());
if (rc == RC_OK)
{
asyncTask([this, url]() {
std::string image = getOrDownloadImage(url.c_str());
notifier.showChallenge(image);
}
});
});
}
}
void Achievements::handleAchievementChallengeIndicatorHideEvent(const rc_client_event_t *event)
{
const rc_client_achievement_t* cheevo = event->achievement;
INFO_LOG(COMMON, "RA: Challenge hidden: %s", cheevo->title);
asyncTask([this, cheevo]() {
char url[128];
int rc = rc_client_achievement_get_image_url(cheevo, RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED, url, sizeof(url));
if (rc == RC_OK)
{
std::string image = getOrDownloadImage(url);
std::string url(512, '\0');
int rc = rc_client_achievement_get_image_url(cheevo, RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED, url.data(), url.size());
if (rc == RC_OK)
{
asyncTask([this, url]() {
std::string image = getOrDownloadImage(url.c_str());
notifier.hideChallenge(image);
}
});
});
}
}
void Achievements::handleLeaderboardStarted(const rc_client_event_t *event)
@@ -685,18 +656,21 @@ void Achievements::handleUpdateLeaderboardTracker(const rc_client_event_t *event
void Achievements::handleGameCompleted(const rc_client_event_t *event)
{
const rc_client_game_t* game = rc_client_get_game_info(rc_client);
asyncTask([this, game]() {
std::string text1 = (rc_client_get_hardcore_enabled(rc_client) ? "Mastered " : "Completed ") + std::string(game->title);
rc_client_user_game_summary_t summary;
rc_client_get_user_game_summary(rc_client, &summary);
std::stringstream ss;
ss << summary.num_unlocked_achievements << " achievements, " << summary.points_unlocked << " points";
std::string text2(ss.str());
std::string text3 = rc_client_get_user_info(rc_client)->display_name;
std::string url(512, '\0');
if (rc_client_game_get_image_url(game, url.data(), url.size()) != RC_OK)
url.clear();
asyncTask([this, url, text1, text2, text3]() {
std::string image;
char url[128];
if (rc_client_game_get_image_url(game, url, sizeof(url)) == RC_OK)
image = getOrDownloadImage(url);
std::string text1 = (rc_client_get_hardcore_enabled(rc_client) ? "Mastered " : "Completed ") + std::string(game->title);
rc_client_user_game_summary_t summary;
rc_client_get_user_game_summary(rc_client, &summary);
std::stringstream ss;
ss << summary.num_unlocked_achievements << " achievements, " << summary.points_unlocked << " points";
std::string text3 = rc_client_get_user_info(rc_client)->display_name;
notifier.notify(Notification::Mastery, image, text1, ss.str(), text3);
if (!url.empty())
image = getOrDownloadImage(url.c_str());
notifier.notify(Notification::Mastery, image, text1, text2, text3);
});
}
@@ -711,12 +685,15 @@ void Achievements::handleHideAchievementProgress(const rc_client_event_t *event)
void Achievements::handleUpdateAchievementProgress(const rc_client_event_t *event)
{
const rc_client_achievement_t* cheevo = event->achievement;
asyncTask([this, cheevo]() {
char url[128];
std::string url(512, '\0');
if (rc_client_achievement_get_image_url(cheevo, RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE, url.data(), url.size()) != RC_OK)
url.clear();
std::string progress(cheevo->measured_progress);
asyncTask([this, url, progress]() {
std::string image;
if (rc_client_achievement_get_image_url(cheevo, RC_CLIENT_ACHIEVEMENT_STATE_ACTIVE, url, sizeof(url)) == RC_OK)
image = getOrDownloadImage(url);
notifier.notify(Notification::Progress, image, cheevo->measured_progress);
if (!url.empty())
image = getOrDownloadImage(url.c_str());
notifier.notify(Notification::Progress, image, progress);
});
}
@@ -771,8 +748,7 @@ std::string Achievements::getGameHash()
{
if (settings.platform.isConsole())
{
const u32 diskType = libGDR_GetDiscType();
if (diskType == NoDisk || diskType == Open)
if (!gdr::isLoaded())
return {};
// Reopen the disk locally to avoid threading issues (CHD)
try {
@@ -806,15 +782,19 @@ std::string Achievements::getGameHash()
return hash;
}
void Achievements::pauseGame() {
void Achievements::pauseGame()
{
paused = true;
if (active)
idleThread.start();
}
void Achievements::resumeGame()
{
paused = false;
if (config::EnableAchievements)
if (config::EnableAchievements && !settings.naomi.slave)
{
idleThread.stop();
loadGame();
if (settings.raHardcoreMode && !config::AchievementsHardcoreMode)
{
@@ -919,21 +899,24 @@ void Achievements::gameLoaded(int result, const char *errorMessage)
settings.raHardcoreMode = false;
else
settings.raHardcoreMode = (bool)rc_client_get_hardcore_enabled(rc_client);
asyncTask([this, info]() {
std::string url(512, '\0');
if (rc_client_game_get_image_url(info, url.data(), url.size()) != RC_OK)
url.clear();
std::string text1(info->title);
rc_client_user_game_summary_t summary;
rc_client_get_user_game_summary(rc_client, &summary);
std::string text2;
if (summary.num_core_achievements > 0)
text2 = "You have " + std::to_string(summary.num_unlocked_achievements)
+ " of " + std::to_string(summary.num_core_achievements) + " achievements unlocked.";
else
text2 = "This game has no achievements.";
asyncTask([this, url, text1, text2]() {
std::string image;
char url[512];
if (rc_client_game_get_image_url(info, url, sizeof(url)) == RC_OK)
image = getOrDownloadImage(url);
rc_client_user_game_summary_t summary;
rc_client_get_user_game_summary(rc_client, &summary);
std::string text;
if (summary.num_core_achievements > 0)
text = "You have " + std::to_string(summary.num_unlocked_achievements)
+ " of " + std::to_string(summary.num_core_achievements) + " achievements unlocked.";
else
text = "This game has no achievements.";
std::string text2 = settings.raHardcoreMode ? "Hardcore Mode" : "";
notifier.notify(Notification::Login, image, info->title, text, text2);
if (!url.empty())
image = getOrDownloadImage(url.c_str());
std::string text3 = settings.raHardcoreMode ? "Hardcore Mode" : "";
notifier.notify(Notification::Login, image, text1, text2, text3);
});
}
@@ -945,15 +928,15 @@ void Achievements::unloadGame()
paused = false;
EventManager::unlisten(Event::VBlank, emuEventCallback, this);
// wait for all async tasks before unloading the game
stopThread();
startThread();
stopThreads();
rc_client_unload_game(rc_client);
settings.raHardcoreMode = false;
}
void Achievements::diskChange()
{
if (!active)
if (!active || settings.content.path.empty())
// Don't unload the game when the lid is open while swapping disks
return;
std::string hash = getGameHash();
if (hash == "") {
+11 -8
View File
@@ -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;
}
+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;
}
+20
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; };
@@ -60,6 +63,7 @@ void WriteSample(s16 r, s16 l)
void InitAudio()
{
registerForEvents();
TermAudio();
std::string slug = config::AudioBackend;
@@ -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);
}
+14 -9
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)
@@ -100,7 +105,7 @@
#endif
#endif
#if !defined(LIBRETRO) && !defined(TARGET_NO_EXCEPTIONS)
#if !defined(LIBRETRO)
#define USE_GGPO
#endif
+9
View File
@@ -130,3 +130,12 @@ void cfgSetAutoSave(bool autoSave)
if (autoSave)
saveConfigFile();
}
void cfgSaveFloat(const std::string& section, const std::string& key, float value)
{
cfgdb.set_float(section, key, value);
}
float cfgLoadFloat(const std::string& section, const std::string& key, float def)
{
return cfgdb.get_float(section, key, def);
}
+2
View File
@@ -11,6 +11,8 @@ std::string cfgLoadStr(const std::string& section, const std::string& key, const
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 cfgSaveFloat(const std::string& section, const std::string& key, float value);
float cfgLoadFloat(const std::string& section, const std::string& key, float 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);
+21
View File
@@ -47,6 +47,11 @@ bool ConfigEntry::get_bool()
}
}
float ConfigEntry::get_float()
{
return atof(this->value.c_str());
}
/* ConfigSection */
bool ConfigSection::has_entry(const std::string& name)
@@ -192,6 +197,15 @@ bool ConfigFile::get_bool(const std::string& section_name, const std::string& en
}
}
float ConfigFile::get_float(const std::string& section_name, const std::string& entry_name, float default_value)
{
ConfigEntry* entry = get_entry(section_name, entry_name);
if (entry == nullptr)
return default_value;
else
return entry->get_float();
}
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);
@@ -222,6 +236,13 @@ void ConfigFile::set_bool(const std::string& section_name, const std::string& en
this->set(section_name, entry_name, str_value, is_virtual);
}
void ConfigFile::set_float(const std::string& section_name, const std::string& entry_name, float value, bool is_virtual)
{
std::stringstream str_value;
str_value << value;
this->set(section_name, entry_name, str_value.str(), is_virtual);
}
void ConfigFile::parse(FILE* file)
{
if (file == nullptr)
+3
View File
@@ -13,6 +13,7 @@ struct ConfigEntry {
int get_int();
bool get_bool();
int64_t get_int64();
float get_float();
};
struct ConfigSection {
@@ -45,11 +46,13 @@ struct ConfigFile {
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);
float get_float(const std::string& section_name, const std::string& entry_name, float default_value = 0.f);
/* 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 set_float(const std::string& section_name, const std::string& entry_name, float 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);
+23 -11
View File
@@ -105,7 +105,11 @@ 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);
@@ -132,6 +136,10 @@ Option<std::vector<std::string>, false> ContentPath("Dreamcast.ContentPath");
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");
@@ -143,7 +151,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");
@@ -158,6 +166,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");
Option<bool> UseDCNet("DCNet", false, "network");
OptionString ISPUsername("ISPUsername", "flycast1", "network");
#ifdef USE_OMX
Option<int> OmxAudioLatency("audio_latency", 100, "omx");
@@ -168,6 +178,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"),
@@ -175,23 +186,24 @@ 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<MapleDeviceType>("device4.1", MDT_None, "input"),
Option<MapleDeviceType>("device4.2", MDT_None, "input")}},
}};
Option<bool> PerGameVmu("PerGameVmu", false, "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");
+10 -8
View File
@@ -202,11 +202,7 @@ protected:
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 cfgLoadFloat(section, name, value);
}
template <typename U = T>
@@ -301,9 +297,7 @@ protected:
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);
cfgSaveFloat(section, name, value);
}
template <typename U = T>
@@ -498,6 +492,10 @@ extern Option<std::vector<std::string>, false> ContentPath;
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;
@@ -524,6 +522,8 @@ extern Option<int> GGPOChatTimeout;
extern Option<bool> NetworkOutput;
extern Option<int> MultiboardSlaves;
extern Option<bool> BattleCableEnable;
extern Option<bool> UseDCNet;
extern OptionString ISPUsername;
#ifdef USE_OMX
extern Option<int> OmxAudioLatency;
@@ -534,6 +534,7 @@ 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 Option<bool> PerGameVmu;
@@ -542,6 +543,7 @@ extern Option<bool, false> UseRawInput;
#else
constexpr bool UseRawInput = false;
#endif
extern Option<bool> UsePhysicalVmuMemory;
#ifdef USE_LUA
extern Option<std::string, false> LuaFileName;
+145 -32
View File
@@ -83,7 +83,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)
@@ -165,8 +165,8 @@ 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)
{ "T15103D 50", nullptr, { 0x1EEE78 }, { 0x3F400000 } }, // PenPen (PAL)
@@ -377,6 +377,17 @@ 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)
{
@@ -421,7 +432,8 @@ void CheatManager::loadCheatFile(const std::string& filename)
}
setActive(!cheats.empty());
INFO_LOG(COMMON, "%d cheats loaded", (int)cheats.size());
cfgSaveStr("cheats", gameId, filename);
if (!cheats.empty())
cfgSaveStr("cheats", gameId, filename);
#endif
}
@@ -454,31 +466,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
}
@@ -494,6 +481,68 @@ 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 == "T40214N") { // The Next Tetris (US)
cheats.emplace_back(Cheat::Type::runNextIfEq, "bypass speed ifeq", true, 32, 0x0016d5d4, 0x2f862fe6, true);
cheats.emplace_back(Cheat::Type::setValue, "bypass speed check", true, 32, 0x0016d5d4, 0xe001000b, true);
}
if (cheats.size() > cheatCount)
setActive(true);
}
@@ -685,6 +734,42 @@ static std::vector<u32> parseCodes(const std::string& s)
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);
@@ -700,6 +785,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:
@@ -813,9 +914,17 @@ 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("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
@@ -873,6 +982,10 @@ void CheatManager::addGameSharkCheat(const std::string& name, const std::string&
conditionCheat = cheat;
}
break;
// TODO 0xF: 0F-XXXXXX 0000YYYY
// 16-Bit Write Once Immediately. (Activator code)
default:
throw FlycastException("Unsupported cheat type");
}
+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)
+384 -384
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
@@ -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)
+1 -1
View File
@@ -11661,7 +11661,7 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result)
// Compute distance between boxes
// FIXME-NAV: Introducing biases for vertical navigation, needs to be removed.
float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
float dby = cand.Min.y == curr.Max.y || cand.Max.y == curr.Min.y
float dby = ImFabs(cand.Min.y - curr.Max.y) < 1 || ImFabs(cand.Max.y - curr.Min.y) < 1
// Scale down on Y to keep using box-distance for vertically touching items
? NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f))
: NavScoreItemDistInterval(cand.Min.y, cand.Max.y, curr.Min.y, curr.Max.y);
+11 -1
View File
@@ -2773,6 +2773,9 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
dst_tmp_array.resize(atlas->Fonts.Size);
memset(src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes());
memset(dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes());
ImVector<bool> src_tmp_array_skip;
src_tmp_array_skip.resize(atlas->ConfigData.Size);
memset(src_tmp_array_skip.Data, 0, (size_t)src_tmp_array_skip.size_in_bytes());
// 1. Initialize font loading structure, check font data validity
for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++)
@@ -2797,7 +2800,8 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
if (!stbtt_InitFont(&src_tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset))
{
IM_ASSERT(0 && "stbtt_InitFont(): failed to parse FontData. It is correct and complete? Check FontDataSize.");
return false;
src_tmp_array_skip[src_i] = true;
continue;
}
// Measure highest codepoints
@@ -2818,6 +2822,8 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
int total_glyphs_count = 0;
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
{
if (src_tmp_array_skip[src_i])
continue;
ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1);
@@ -2844,6 +2850,8 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
// 3. Unpack our bit map into a flat list (we now have all the Unicode points that we know are requested _and_ available _and_ not overlapping another)
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
{
if (src_tmp_array_skip[src_i])
continue;
ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount);
UnpackBitVectorToFlatIndexList(&src_tmp.GlyphsSet, &src_tmp.GlyphsList);
@@ -2974,6 +2982,8 @@ static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
// 9. Setup ImFont and glyphs for runtime
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
{
if (src_tmp_array_skip[src_i])
continue;
// When merging fonts with MergeMode=true:
// - We can have multiple input fonts writing into a same destination font.
// - dst_font->ConfigData is != from cfg which is our source configuration.
@@ -31,7 +31,7 @@
#endif
#endif
#ifdef _WIN32
#if defined(_WIN32) && !defined(USE_LIBCDIO) // libcdio has its equivalent version
#undef fopen
void *fopen_utf8(const char * filename, const char * mode)
+17 -10
View File
@@ -190,7 +190,9 @@ int main(int argc, char *argv[]) { }" HAVE_NULLABLE)
test_big_endian(WORDS_BIGENDIAN)
find_package(ZLIB 1.1.2 REQUIRED)
if(NOT TARGET zlibstatic)
find_package(ZLIB 1.1.2 REQUIRED)
endif()
# so developers on systems where zlib is named differently (Windows, sometimes)
# can override the name used in the pkg-config file
if (NOT ZLIB_LINK_LIBRARY_NAME)
@@ -239,17 +241,22 @@ if(ENABLE_LZMA)
endif(ENABLE_LZMA)
if(ENABLE_ZSTD)
find_package(zstd 1.3.6)
if(zstd_FOUND)
if(TARGET libzstd_static)
set(zstd_TARGET libzstd_static)
set(HAVE_LIBZSTD 1)
if(TARGET zstd::libzstd_shared)
set(zstd_TARGET zstd::libzstd_shared)
else()
set(zstd_TARGET zstd::libzstd_static)
endif()
else()
message(WARNING "-- zstd library not found; zstandard support disabled")
endif(zstd_FOUND)
find_package(zstd 1.3.6)
if(zstd_FOUND)
set(HAVE_LIBZSTD 1)
if(TARGET zstd::libzstd_shared)
set(zstd_TARGET zstd::libzstd_shared)
else()
set(zstd_TARGET zstd::libzstd_static)
endif()
else()
message(WARNING "-- zstd library not found; zstandard support disabled")
endif()
endif()
endif(ENABLE_ZSTD)
if (COMMONCRYPTO_FOUND)
+5 -1
View File
@@ -175,7 +175,11 @@ if(SHARED_LIB_VERSIONNING)
set_target_properties(zip PROPERTIES VERSION 5.5 SOVERSION 5)
endif()
target_link_libraries(zip PRIVATE ZLIB::ZLIB)
if (TARGET zlibstatic)
target_link_libraries(zip PRIVATE zlibstatic)
else()
target_link_libraries(zip PRIVATE ZLIB::ZLIB)
endif()
target_include_directories(zip
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib>
@@ -76,6 +76,9 @@ int _zip_win32_error_to_errno(DWORD win32err);
#ifdef __clang__
#define DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wincompatible-function-pointer-types\"")
#define DONT_WARN_INCOMPATIBLE_FN_PTR_END _Pragma("GCC diagnostic pop")
#elif defined(__GNUC__) && __GNUC__ > 13
#define DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wincompatible-pointer-types\"")
#define DONT_WARN_INCOMPATIBLE_FN_PTR_END _Pragma("GCC diagnostic pop")
#else
#define DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN
#define DONT_WARN_INCOMPATIBLE_FN_PTR_END
+1 -1
View File
@@ -338,7 +338,7 @@ receiveDevicesFromMiniSSDPD(int s, int * error)
#ifdef DEBUG
printf(" usnsize=%u\n", usnsize);
#endif /* DEBUG */
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize+3);
if(tmp == NULL) {
if (error)
*error = MINISSDPC_MEMORY_ERROR;
@@ -7,6 +7,8 @@
#include <windows.h>
#pragma pack(pop)
#define PICO_SUPPORT_THREADING
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
@@ -54,6 +56,15 @@ static inline void PICO_IDLE(void)
#define alloca _alloca
#ifdef PICO_SUPPORT_THREADING
#define PICO_SUPPORT_MUTEX
/* mutex implementations */
extern void* pico_mutex_init(void);
extern void pico_mutex_lock(void* mux);
extern void pico_mutex_unlock(void* mux);
extern void pico_mutex_deinit(void* mux);
#endif
#endif /* PICO_SUPPORT_MSVC */
+1
View File
@@ -170,6 +170,7 @@ struct pico_ip_mreq_source {
#define PICO_SOCK_EV_CLOSE 8u
#define PICO_SOCK_EV_FIN 0x10u
#define PICO_SOCK_EV_ERR 0x80u
#define PICO_SOCK_EV_DEL 0x100u
struct pico_msginfo {
struct pico_device *dev;
+1 -1
View File
@@ -9,7 +9,7 @@
#include "pico_frame.h"
#include "pico_constants.h"
#define PICO_MAX_TIMERS 20
#define PICO_MAX_TIMERS 50
#define PICO_ETH_MRU (1514u)
#define PICO_IP_MRU (1500u)
+5 -4
View File
@@ -295,7 +295,7 @@ static int pico_ethernet_ipv6_dst(struct pico_frame *f, struct pico_eth *const d
/* Ethernet send, first attempt: try our own address.
* Returns 0 if the packet is not for us.
* Returns 1 if the packet is cloned to our own receive queue, so the caller can discard the original frame.
* Returns 1 if the packet is cloned to our own receive queue and the original frame is dicarded.
* */
static int32_t pico_ethsend_local(struct pico_frame *f, struct pico_eth_hdr *hdr)
{
@@ -308,7 +308,9 @@ static int32_t pico_ethsend_local(struct pico_frame *f, struct pico_eth_hdr *hdr
dbg("sending out packet destined for our own mac\n");
if (pico_ethernet_receive(clone) < 0) {
dbg("pico_ethernet_receive() failed\n");
return 0;
}
pico_frame_discard(f);
return 1;
}
@@ -317,13 +319,12 @@ static int32_t pico_ethsend_local(struct pico_frame *f, struct pico_eth_hdr *hdr
/* Ethernet send, second attempt: try bcast.
* Returns 0 if the packet is not bcast, so it will be handled somewhere else.
* Returns 1 if the packet is handled by the pico_device_broadcast() function, so it can be discarded.
* Returns 1 if the packet is handled by the pico_device_broadcast() function and is discarded.
* */
static int32_t pico_ethsend_bcast(struct pico_frame *f)
{
if (IS_LIMITED_BCAST(f)) {
(void)pico_device_broadcast(f); /* We can discard broadcast even if it's not sent. */
return 1;
return (pico_device_broadcast(f) > 0); // Return 1 on success, ret > 0
}
return 0;
+4
View File
@@ -242,6 +242,10 @@ static int8_t pico_icmp4_send_echo(struct pico_icmp4_ping_cookie *cookie)
if (!dev)
return -1;
// prevent overflow
if (cookie->size > PICO_ICMP_MAXCOOKIE)
return -1;
echo = pico_proto_ipv4.alloc(&pico_proto_ipv4, dev, (uint16_t)(PICO_ICMPHDR_UN_SIZE + cookie->size));
if (!echo)
return -1;
+1 -1
View File
@@ -92,7 +92,7 @@ PACKED_STRUCT_DEF pico_icmp4_hdr {
#define PICO_ICMP_MASKREPLY 18
#define PICO_ICMP_MAXTYPE 18
#define PICO_ICMP_MAXCOOKIE 65528
#define PICO_ICMP_UNREACH_NET 0
#define PICO_ICMP_UNREACH_HOST 1
@@ -190,7 +190,6 @@ static int socket_tcp_do_deliver(struct pico_socket *s, struct pico_frame *f)
return 0;
}
dbg("TCP SOCKET> Not s.\n");
return -1;
}
+23 -6
View File
@@ -826,6 +826,8 @@ static void tcp_rcv_sack(struct pico_socket_tcp *t, uint8_t *opt, int len)
static int tcpopt_len_check(uint32_t *idx, uint8_t len, uint8_t expected)
{
if (len != expected) {
if (len < 2)
return -1;
*idx = *idx + len - 2;
return -1;
}
@@ -880,7 +882,7 @@ static inline void tcp_parse_option_timestamp(struct pico_socket_tcp *t, struct
t->ts_nxt = long_be(tsval);
}
static void tcp_parse_options(struct pico_frame *f)
static int tcp_parse_options(struct pico_frame *f)
{
struct pico_socket_tcp *t = (struct pico_socket_tcp *)f->sock;
uint8_t *opt = f->transport_hdr + PICO_SIZE_TCPHDR;
@@ -897,6 +899,10 @@ static void tcp_parse_options(struct pico_frame *f)
if (f->payload && ((opt + i) > f->payload))
break;
if (len == 0) {
return -1;
}
tcp_dbg_options("Received option '%d', len = %d \n", type, len);
switch (type) {
case PICO_TCP_OPTION_NOOP:
@@ -924,6 +930,7 @@ static void tcp_parse_options(struct pico_frame *f)
i = i + len - 2;
}
}
return 0;
}
static inline void tcp_send_add_tcpflags(struct pico_socket_tcp *ts, struct pico_frame *f)
@@ -1755,7 +1762,8 @@ static int tcp_data_in(struct pico_socket *s, struct pico_frame *f)
(void)hdr;
if (((hdr->len & 0xf0u) >> 2u) <= f->transport_len) {
tcp_parse_options(f);
if (tcp_parse_options(f) < 0)
return -1;
f->payload = f->transport_hdr + ((hdr->len & 0xf0u) >> 2u);
f->payload_len = payload_len;
tcp_dbg("TCP> Received segment. (exp: %x got: %x)\n", t->rcv_nxt, SEQN(f));
@@ -2130,7 +2138,8 @@ static int tcp_ack(struct pico_socket *s, struct pico_frame *f)
tcp_ack_dbg(s, f);
#endif
tcp_parse_options(f);
if (tcp_parse_options(f) < 0)
return -1;
t->recv_wnd = short_be(hdr->rwnd);
acked = (uint16_t)tcp_ack_advance_una(t, f, &acked_timestamp);
@@ -2446,7 +2455,8 @@ static int tcp_syn(struct pico_socket *s, struct pico_frame *f)
f->sock = &new->sock;
mtu = (uint16_t)pico_socket_get_mss(&new->sock);
new->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR);
tcp_parse_options(f);
if (tcp_parse_options(f) < 0)
return -1;
new->tcpq_in.max_size = PICO_DEFAULT_SOCKETQ;
new->tcpq_out.max_size = PICO_DEFAULT_SOCKETQ;
new->tcpq_hold.max_size = 2u * mtu;
@@ -2793,7 +2803,7 @@ static uint8_t invalid_flags(struct pico_socket *s, uint8_t flags)
{ /* PICO_SOCKET_STATE_TCP_UNDEF */ 0, },
{ /* PICO_SOCKET_STATE_TCP_CLOSED */ 0, },
{ /* PICO_SOCKET_STATE_TCP_LISTEN */ PICO_TCP_SYN, PICO_TCP_SYN | PICO_TCP_PSH },
{ /* PICO_SOCKET_STATE_TCP_SYN_SENT */ PICO_TCP_SYNACK, PICO_TCP_RST, PICO_TCP_RSTACK},
{ /* PICO_SOCKET_STATE_TCP_SYN_SENT */ PICO_TCP_SYNACK, PICO_TCP_RST, PICO_TCP_RSTACK, PICO_TCP_SYNACK | PICO_TCP_PSH },
{ /* PICO_SOCKET_STATE_TCP_SYN_RECV */ PICO_TCP_SYN, PICO_TCP_ACK, PICO_TCP_PSH, PICO_TCP_PSHACK, PICO_TCP_FINACK, PICO_TCP_FINPSHACK, PICO_TCP_RST},
{ /* PICO_SOCKET_STATE_TCP_ESTABLISHED*/ PICO_TCP_SYN, PICO_TCP_SYNACK, PICO_TCP_ACK, PICO_TCP_PSH, PICO_TCP_PSHACK, PICO_TCP_FIN, PICO_TCP_FINACK, PICO_TCP_FINPSHACK, PICO_TCP_RST, PICO_TCP_RSTACK},
{ /* PICO_SOCKET_STATE_TCP_CLOSE_WAIT */ PICO_TCP_SYNACK, PICO_TCP_ACK, PICO_TCP_PSH, PICO_TCP_PSHACK, PICO_TCP_FIN, PICO_TCP_FINACK, PICO_TCP_FINPSHACK, PICO_TCP_RST},
@@ -2864,6 +2874,11 @@ int pico_tcp_input(struct pico_socket *s, struct pico_frame *f)
// tcp_dbg("[sam] TCP> s->state >> 8 = %u\n", s->state >> 8);
tcp_dbg("[tcp input] socket: %p state: %d <-- local port:%u remote port: %u seq: 0x%08x ack: 0x%08x flags: 0x%02x t_len: %u, hdr: %u payload: %d\n", s, s->state >> 8, short_be(hdr->trans.dport), short_be(hdr->trans.sport), SEQN(f), ACKN(f), hdr->flags, f->transport_len, (hdr->len & 0xf0) >> 2, f->payload_len );
if ((f->payload + f->payload_len) > (f->buffer + f->buffer_len)) {
tcp_dbg("TCP> Invalid payload len %04x\n", f->payload_len);
pico_frame_discard(f);
return -1;
}
/* This copy of the frame has the current socket as owner */
f->sock = s;
s->timestamp = TCP_TIME;
@@ -2874,7 +2889,9 @@ int pico_tcp_input(struct pico_socket *s, struct pico_frame *f)
}
else if (flags == PICO_TCP_SYN || flags == (PICO_TCP_SYN | PICO_TCP_PSH)) {
tcp_action_call(action->syn, s, f);
} else if (flags == (PICO_TCP_SYN | PICO_TCP_ACK)) {
} else if (flags == (PICO_TCP_SYN | PICO_TCP_ACK)
// Windows CE / DirectPlay sets the PSH flag on SYN|ACK packets, which is normally invalid
|| flags == (PICO_TCP_SYN | PICO_TCP_ACK | PICO_TCP_PSH)) {
tcp_action_call(action->synack, s, f);
} else {
ret = tcp_action_by_flags(action, s, f, flags);
+16 -1
View File
@@ -451,6 +451,7 @@ int32_t pico_device_broadcast(struct pico_frame *f)
{
struct pico_tree_node *index;
int32_t ret = -1;
int sent = 0;
pico_tree_foreach(index, &Device_tree)
{
@@ -463,14 +464,28 @@ int32_t pico_device_broadcast(struct pico_frame *f)
break;
copy->dev = dev;
copy->dev->send(copy->dev, copy->start, (int)copy->len);
ret = copy->dev->send(copy->dev, copy->start, (int)copy->len);
/* FIXME: If a device driver returns zero (which means the device
* driver is currently busy) there is no means to retry the
* broadcast operation later. */
pico_frame_discard(copy);
}
else
{
ret = f->dev->send(f->dev, f->start, (int)f->len);
/* FIXME: If a device driver returns zero (which means the device
* driver is currently busy) there is no means to retry the
* broadcast operation later. */
}
/* FIXME: If at least one device driver was able to sent the frame on
* the wire, the broadcast operation will be considered successful. */
if (ret > 0) {
sent = 1;
}
}
ret = sent ? f->len : -1;
pico_frame_discard(f);
return ret;
}
+2
View File
@@ -473,6 +473,8 @@ static void socket_garbage_collect(pico_time now, void *arg)
struct pico_socket *s = (struct pico_socket *) arg;
IGNORE_PARAMETER(now);
if (s->wakeup)
s->wakeup(PICO_SOCK_EV_DEL, s);
socket_clean_queues(s);
PICO_FREE(s);
}
+28 -32
View File
@@ -1,44 +1,40 @@
cmake_minimum_required(VERSION 2.6...3.0.2)
cmake_minimum_required(VERSION 3.5...4.0.0)
project(xbyak CXX)
file(GLOB headers xbyak/*.h)
if (DEFINED CMAKE_VERSION AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.0.2)
include(GNUInstallDirs)
add_library(${PROJECT_NAME} INTERFACE)
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
target_include_directories(
${PROJECT_NAME} INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
include(GNUInstallDirs)
add_library(${PROJECT_NAME} INTERFACE)
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
install(
TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}-targets
)
target_include_directories(
${PROJECT_NAME} INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
configure_file(
cmake/config.cmake.in
${PROJECT_NAME}Config.cmake
@ONLY
)
install(
TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}-targets
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
configure_file(
cmake/config.cmake.in
${PROJECT_NAME}Config.cmake
@ONLY
)
install(
EXPORT ${PROJECT_NAME}-targets
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
elseif(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
set(CMAKE_INSTALL_INCLUDEDIR "include")
endif()
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
install(
EXPORT ${PROJECT_NAME}-targets
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
install(
FILES ${headers}
+7
View File
@@ -0,0 +1,7 @@
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
+644
View File
@@ -0,0 +1,644 @@
# Known critical issues:
# - AVX512 related tests are incomplete. Because default environment of
# GitHub Actions doesn't guarantee to support AVX512.
# As of May 2021, they're using Xeon E5-2673 (which doesn't support
# AVX512) and Xeon Platinum 8171M (which supports AVX512).
# See also https://github.com/actions/runner/issues/1069
#
# In this CI script, it always run `make default` which compiles xxHash
# with AVX512 intrinsics. But if test runner doesn't support AVX512,
# it doesn't run `make check` which tests runtime error/consistency.
# It means that this test stochastically detects a failure in AVX512
# code path.
#
# Known issues:
# - This test script ignores exit code of cppcheck which can see under
# Job:Linux x64 misc tests > cppcheck in the GitHub Actions report.
# Because xxHash project doesn't 100% follow their recommendation.
# Also sometimes it reports false positives.
#
# - GitHub Actions doesn't support Visual Studio 2015 and 2013.
# https://github.com/actions/virtual-environments/issues/387
#
# - Setup procedure for msys2 environment is painfully slow. It takes
# 3..5 minutes.
#
# Notes:
# - You can investigate various information at the right pane of GitHub
# Actions report page.
#
# | Item | Section in the right pane |
# | ------------------------- | ------------------------------------- |
# | OS, VM | Set up job |
# | git repo, commit hash | Run actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 |
# | gcc, tools | Environment info |
#
# - To fail earlier, order of tests in the same job are roughly sorted by
# elapsed time.
#
# Todos:
# - [ ] Linux: Add native ARM runner.
# - [ ] Linux: Add native ARM64 runner.
# - [ ] Linux: Add native PPC64LE runner.
# - [ ] Linux: Add native S390X runner.
# - [ ] Windows: Add VS2013.
# - [ ] Windows: Add VS2015.
# - [ ] Windows: Add clang for msys2.
# - [ ] Windows: Add native or emulated ARM runner.
# - [ ] Windows: Add native or emulated ARM64 runner.
# Name of the workflow is also displayed as a SVG badge
name: xxHash CI tests
on: [push, pull_request]
concurrency:
group: fast-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
xxhash-c-compilers:
name: CC=${{ matrix.cc }}, ${{ matrix.os }}
strategy:
fail-fast: false # 'false' means Don't stop matrix workflows even if some matrix entry fails.
matrix:
include: [
# You can access the following values via ${{ matrix.??? }}
#
# pkgs : apt-get package names. It can include multiple package names which are delimited by space.
# cc : C compiler executable.
# cxx : C++ compiler executable for `make ctocpptest`.
# os : GitHub Actions YAML workflow label. See https://github.com/actions/virtual-environments#available-environments
# cc
{ pkgs: '', cc: cc, cxx: c++, os: ubuntu-latest, },
# gcc
{ pkgs: '', cc: gcc, cxx: g++, os: ubuntu-latest, },
# { pkgs: 'gcc-13 g++-13 lib32gcc-13-dev', cc: gcc-13, cxx: g++-13, os: ubuntu-22.04, }, # currently failing
{ pkgs: 'gcc-12 g++-12 lib32gcc-12-dev', cc: gcc-12, cxx: g++-12, os: ubuntu-22.04, },
{ pkgs: 'gcc-11 g++-11 lib32gcc-11-dev', cc: gcc-11, cxx: g++-11, os: ubuntu-22.04, },
{ pkgs: 'gcc-10 g++-10 lib32gcc-10-dev', cc: gcc-10, cxx: g++-10, os: ubuntu-22.04, },
{ pkgs: 'gcc-9 g++-9 lib32gcc-9-dev', cc: gcc-9, cxx: g++-9, os: ubuntu-22.04, },
{ pkgs: 'gcc-8 g++-8 lib32gcc-8-dev', cc: gcc-8, cxx: g++-8, os: ubuntu-20.04, },
{ pkgs: 'gcc-7 g++-7 lib32gcc-7-dev', cc: gcc-7, cxx: g++-7, os: ubuntu-20.04, },
# clang
{ pkgs: '', cc: clang, cxx: clang++, os: ubuntu-latest, },
{ pkgs: 'clang-15', cc: clang-15, cxx: clang++-15, os: ubuntu-22.04, },
{ pkgs: 'clang-14', cc: clang-14, cxx: clang++-14, os: ubuntu-22.04, },
{ pkgs: 'clang-13', cc: clang-13, cxx: clang++-13, os: ubuntu-22.04, },
{ pkgs: 'clang-12', cc: clang-12, cxx: clang++-12, os: ubuntu-22.04, },
{ pkgs: 'clang-11', cc: clang-11, cxx: clang++-11, os: ubuntu-22.04, },
{ pkgs: 'clang-10', cc: clang-10, cxx: clang++-10, os: ubuntu-20.04, },
{ pkgs: 'clang-9', cc: clang-9, cxx: clang++-9, os: ubuntu-20.04, },
{ pkgs: 'clang-8', cc: clang-8, cxx: clang++-8, os: ubuntu-20.04, },
{ pkgs: 'clang-7', cc: clang-7, cxx: clang++-7, os: ubuntu-20.04, },
{ pkgs: 'clang-6.0', cc: clang-6.0, cxx: clang++-6.0, os: ubuntu-20.04, },
]
runs-on: ${{ matrix.os }}
env: # Set environment variables
# We globally set CC and CXX to improve compatibility with .travis.yml
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: apt-get install
run: |
sudo apt-get update
sudo apt-get install gcc-multilib
sudo apt-get install ${{ matrix.pkgs }}
- name: Environment info
run: |
echo && type $CC && which $CC && $CC --version
echo && type $CXX && which $CXX && $CXX --version
echo && type make && make -v
echo && cat /proc/cpuinfo || echo /proc/cpuinfo is not present
- name: C90 + no-long-long compliance
if: always()
run: |
CFLAGS="-std=c90 -pedantic -Wno-long-long -Werror" make clean xxhsum
- name: C90 + XXH_NO_LONG_LONG
if: always()
run: |
# strict c90, with no long long support; resulting in no XXH64_* symbol
make clean c90test
- name: dispatch
if: always()
run: |
# removing sign conversion warnings due to a bug in gcc-5's definition of some AVX512 intrinsics
CFLAGS="-Werror" MOREFLAGS="-Wno-sign-conversion" make clean dispatch
- name: DISPATCH=1
if: always()
run: |
CFLAGS="-Wall -Wextra -Werror" make DISPATCH=1 clean default
- name: XXH_SIZE_OPT == 2
if: always()
run: |
CFLAGS="-Os -DXXH_SIZE_OPT=2 -Wall -Wextra -Werror" make clean xxhsum
- name: noxxh3test
if: always()
run: |
# check library can be compiled with XXH_NO_XXH3, resulting in no XXH3_* symbol
make clean noxxh3test
- name: nostreamtest
if: always()
run: |
# check library can be compiled with XXH_NO_STREAM, resulting in no streaming symbols
make clean noxxh3test
- name: make avx512f
run: |
CFLAGS="-O1 -mavx512f -Werror" make clean default
- name: test-all
if: always()
run: |
make clean test-all
ubuntu-consistency:
name: Linux x64 check results consistency
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Environment info
run: |
echo && gcc --version
echo && make -v
echo && cat /proc/cpuinfo || echo /proc/cpuinfo is not present
- name: Scalar code path
run: |
CPPFLAGS=-DXXH_VECTOR=XXH_SCALAR make clean check
- name: SSE2 code path
run: |
CPPFLAGS=-DXXH_VECTOR=XXH_SSE2 make clean check
- name: AVX2 code path
run: |
CPPFLAGS="-mavx2 -DXXH_VECTOR=XXH_AVX2" make clean check
# As for AVX512, see "Known critical issues" at the top of this file
- name: AVX512 code path
run: |
# Run "make check" if /proc/cpuinfo has flags for avx512.
grep -q "^flags.*\bavx512\b" /proc/cpuinfo && CPPFLAGS="-mavx512f -DXXH_VECTOR=XXH_AVX512" make clean check || (echo This test runner does not support AVX512. && $(exit 0))
- name: reroll code path (#240)
run: |
CPPFLAGS=-DXXH_REROLL=1 make clean check
- name: tests/bench
run: |
make -C tests/bench
ubuntu-wasm:
name: Ubuntu Node ${{ matrix.node-version }} WebAssembly/asm.js tests
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 17.x, 18.x]
env:
EM_VERSION: 3.1.33 # TODO: more emsdk versions
EM_CACHE_FOLDER: emsdk-cache-${{ matrix.node-version }}
CC: emcc
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup cache
id: cache-system-libraries
uses: actions/cache@v4
with:
path: ${{env.EM_CACHE_FOLDER}}
key: em${{env.EM_VERSION}}-node${{ matrix.node-version }}-${{ runner.os }}
- name: Setup emsdk
uses: mymindstorm/setup-emsdk@v14
with:
version: ${{env.EM_VERSION}}
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Environment info
run: |
echo && node -p '`node version: ${process.versions.node}, v8 version: ${process.versions.v8}`'
echo && emcc --version
echo && make -v
echo && cat /proc/cpuinfo || echo /proc/cpuinfo is not present
- name: Scalar code path
run: |
CPPFLAGS="-DXXH_VECTOR=XXH_SCALAR" RUN_ENV="node" NODE_JS=1 make clean check
- name: SIMD128 (via NEON SIMDe) code path (XXH_VECTOR=XXH_NEON)
run: |
CPPFLAGS="-DXXH_VECTOR=XXH_NEON -msimd128" RUN_ENV="node" NODE_JS=1 make clean check
- name: Scalar asm.js (-sWASM=0)
run: |
CPPFLAGS="-DXXH_VECTOR=XXH_SCALAR" RUN_ENV="node" NODE_JS=1 LDFLAGS="-sWASM=0" make clean check
ubuntu-misc:
name: Linux x64 misc tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: apt-get install
run: |
sudo apt-get update
sudo apt-get install valgrind cppcheck
- name: Environment info
run: |
echo && gcc --version
echo && clang --version
echo && valgrind --version
echo && cppcheck --version
echo && make -v
echo && cat /proc/cpuinfo || echo /proc/cpuinfo is not present
- name: cppcheck
run: |
# This test script ignores exit code of cppcheck. See knowin issues
# at the top of this file.
make clean cppcheck || echo There are some cppcheck reports
- name: test-mem (valgrind)
run: |
make clean test-mem
- name: usan
run: |
make clean usan
- name: Lint Unicode in root-dir, cli/, tests/, tests/bench/, tests/collisions/.
run: |
make lint-unicode
- name: test-filename-escape
# See also issue #695 - https://github.com/Cyan4973/xxHash/issues/695
run: |
make clean test-filename-escape
- name: test-cli-comment-line
run: |
make clean test-cli-comment-line
ubuntu-cmake-unofficial:
name: Linux x64 cmake unofficial build test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Environment info
run: |
echo && gcc --version
echo && cmake --version
echo && make -v
echo && cat /proc/cpuinfo || echo /proc/cpuinfo is not present
- name: cmake
run: |
cd cmake_unofficial
cmake -Bbuild
cd build
CFLAGS=-Werror make
mkdir -p test_install_dir
DESTDIR=test_install_dir cmake --install .
- name: cmake pkgconfig generation
run: |
cd cmake_unofficial
pwd
ls
rm -rf build
cmake -Bbuild -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_INCLUDEDIR=/usr/include -DCMAKE_INSTALL_LIBDIR=/usr/lib
echo "checking content of libxxhash.pc"
cat build/libxxhash.pc | grep "libdir=/usr/lib"
cat build/libxxhash.pc | grep "includedir=/usr/include"
- name: cmake minimum version v3.10 test
run: |
mkdir -p cmake_bins
cd cmake_bins
wget https://cmake.org/files/v3.10/cmake-3.10.0-Linux-x86_64.tar.gz
tar xzf cmake-3.10.0-Linux-x86_64.tar.gz
cd ../cmake_unofficial
rm -rf build
pwd
ls
mkdir -p build
cd build
../../cmake_bins/cmake-3.10.0-Linux-x86_64/bin/cmake --version
../../cmake_bins/cmake-3.10.0-Linux-x86_64/bin/cmake ..
../../cmake_bins/cmake-3.10.0-Linux-x86_64/bin/cmake --build .
mkdir -p test_install_dir
DESTDIR=test_install_dir ../../cmake_bins/cmake-3.10.0-Linux-x86_64/bin/cmake --install .
rm -rf *
../../cmake_bins/cmake-3.10.0-Linux-x86_64/bin/cmake -DCMAKE_BUILD_TYPE=Debug ..
../../cmake_bins/cmake-3.10.0-Linux-x86_64/bin/cmake --build .
# Linux, { ARM, ARM64, PPC64LE, PPC64, S390X }
# All tests are using QEMU and gcc cross compiler.
qemu-consistency:
name: QEMU ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false # 'false' means Don't stop matrix workflows even if some matrix failed.
matrix:
include: [
{ name: 'ARM', xcc_pkg: gcc-arm-linux-gnueabi, xcc: arm-linux-gnueabi-gcc, xemu_pkg: qemu-system-arm, xemu: qemu-arm-static, os: ubuntu-latest, },
{ name: 'AARCH64', xcc_pkg: gcc-aarch64-linux-gnu, xcc: aarch64-linux-gnu-gcc, xemu_pkg: qemu-system-arm, xemu: qemu-aarch64-static, os: ubuntu-latest, },
{ name: 'PPC64LE', xcc_pkg: gcc-powerpc64le-linux-gnu, xcc: powerpc64le-linux-gnu-gcc, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64le-static, os: ubuntu-latest, },
{ name: 'PPC64', xcc_pkg: gcc-powerpc64-linux-gnu, xcc: powerpc64-linux-gnu-gcc, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64-static, os: ubuntu-latest, },
{ name: 'S390X', xcc_pkg: gcc-s390x-linux-gnu, xcc: s390x-linux-gnu-gcc, xemu_pkg: qemu-system-s390x, xemu: qemu-s390x-static, os: ubuntu-latest, },
{ name: 'MIPS', xcc_pkg: gcc-mips-linux-gnu, xcc: mips-linux-gnu-gcc, xemu_pkg: qemu-system-mips, xemu: qemu-mips-static, os: ubuntu-latest, },
{ name: 'M68K', xcc_pkg: gcc-m68k-linux-gnu, xcc: m68k-linux-gnu-gcc, xemu_pkg: qemu-system-m68k, xemu: qemu-m68k-static, os: ubuntu-latest, },
{ name: 'RISC-V', xcc_pkg: gcc-riscv64-linux-gnu, xcc: riscv64-linux-gnu-gcc, xemu_pkg: qemu-system-riscv64,xemu: qemu-riscv64-static, os: ubuntu-latest, },
# SPARC64 qemu emulation seems broken on Ubuntu-22
{ name: 'SPARC', xcc_pkg: gcc-sparc64-linux-gnu, xcc: sparc64-linux-gnu-gcc, xemu_pkg: qemu-system-sparc, xemu: qemu-sparc64-static, os: ubuntu-20.04, },
{ name: 'LoongArch', xcc_pkg: gcc-14-loongarch64-linux-gnu, xcc: loongarch64-linux-gnu-gcc-14, xemu_pkg: qemu-system-loongarch64, xemu: qemu-loongarch64-static, os: ubuntu-24.04, },
{ name: 'ARM, gcc-10', xcc_pkg: gcc-10-arm-linux-gnueabi, xcc: arm-linux-gnueabi-gcc-10, xemu_pkg: qemu-system-arm, xemu: qemu-arm-static, os: ubuntu-20.04, },
{ name: 'AARCH64, gcc-10', xcc_pkg: gcc-10-aarch64-linux-gnu, xcc: aarch64-linux-gnu-gcc-10, xemu_pkg: qemu-system-arm, xemu: qemu-aarch64-static, os: ubuntu-20.04, },
{ name: 'PPC64LE, gcc-10', xcc_pkg: gcc-10-powerpc64le-linux-gnu, xcc: powerpc64le-linux-gnu-gcc-10, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64le-static, os: ubuntu-20.04, },
{ name: 'PPC64, gcc-10', xcc_pkg: gcc-10-powerpc64-linux-gnu, xcc: powerpc64-linux-gnu-gcc-10, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64-static, os: ubuntu-20.04, },
{ name: 'S390X, gcc-10', xcc_pkg: gcc-10-s390x-linux-gnu, xcc: s390x-linux-gnu-gcc-10, xemu_pkg: qemu-system-s390x, xemu: qemu-s390x-static, os: ubuntu-20.04, },
{ name: 'MIPS, gcc-10', xcc_pkg: gcc-10-mips-linux-gnu, xcc: mips-linux-gnu-gcc-10, xemu_pkg: qemu-system-mips, xemu: qemu-mips-static, os: ubuntu-20.04, },
{ name: 'ARM, gcc-9', xcc_pkg: gcc-9-arm-linux-gnueabi, xcc: arm-linux-gnueabi-gcc-9, xemu_pkg: qemu-system-arm, xemu: qemu-arm-static, os: ubuntu-20.04, },
# SVE tests require at least gcc-10.1
# { name: 'AARCH64, gcc-9', xcc_pkg: gcc-9-aarch64-linux-gnu, xcc: aarch64-linux-gnu-gcc-9, xemu_pkg: qemu-system-arm, xemu: qemu-aarch64-static, os: ubuntu-20.04, },
{ name: 'PPC64LE, gcc-9', xcc_pkg: gcc-9-powerpc64le-linux-gnu, xcc: powerpc64le-linux-gnu-gcc-9, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64le-static, os: ubuntu-20.04, },
{ name: 'PPC64, gcc-9', xcc_pkg: gcc-9-powerpc64-linux-gnu, xcc: powerpc64-linux-gnu-gcc-9, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64-static, os: ubuntu-20.04, },
{ name: 'S390X, gcc-9', xcc_pkg: gcc-9-s390x-linux-gnu, xcc: s390x-linux-gnu-gcc-9, xemu_pkg: qemu-system-s390x, xemu: qemu-s390x-static, os: ubuntu-20.04, },
{ name: 'MIPS, gcc-9', xcc_pkg: gcc-9-mips-linux-gnu, xcc: mips-linux-gnu-gcc-9, xemu_pkg: qemu-system-mips, xemu: qemu-mips-static, os: ubuntu-20.04, },
{ name: 'ARM, gcc-8', xcc_pkg: gcc-8-arm-linux-gnueabi, xcc: arm-linux-gnueabi-gcc-8, xemu_pkg: qemu-system-arm, xemu: qemu-arm-static, os: ubuntu-20.04, },
# aarch64-linux-gnu-gcc-8 linker has an issue for LDFLAGS="-static"
# { name: 'AARCH64, gcc-8', xcc_pkg: gcc-8-aarch64-linux-gnu, xcc: aarch64-linux-gnu-gcc-8, xemu_pkg: qemu-system-arm, xemu: qemu-aarch64-static, os: ubuntu-20.04, },
{ name: 'PPC64LE, gcc-8', xcc_pkg: gcc-8-powerpc64le-linux-gnu, xcc: powerpc64le-linux-gnu-gcc-8, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64le-static, os: ubuntu-20.04, },
{ name: 'PPC64, gcc-8', xcc_pkg: gcc-8-powerpc64-linux-gnu, xcc: powerpc64-linux-gnu-gcc-8, xemu_pkg: qemu-system-ppc, xemu: qemu-ppc64-static, os: ubuntu-20.04, },
{ name: 'S390X, gcc-8', xcc_pkg: gcc-8-s390x-linux-gnu, xcc: s390x-linux-gnu-gcc-8, xemu_pkg: qemu-system-s390x, xemu: qemu-s390x-static, os: ubuntu-20.04, },
# ubuntu-20.04 fails to retrieve gcc-8-mips-linux-gnu for some reason.
# { name: 'MIPS, gcc-8', xcc_pkg: gcc-8-mips-linux-gnu, xcc: mips-linux-gnu-gcc-8, xemu_pkg: qemu-system-mips, xemu: qemu-mips-static, os: ubuntu-20.04, },
]
env: # Set environment variables
XCC: ${{ matrix.xcc }}
XEMU: ${{ matrix.xemu }}
MOREFLAGS: -Werror
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: apt update & install (1)
run: |
sudo apt-get update
sudo apt-get install gcc-multilib g++-multilib qemu-utils qemu-user-static
- name: Environment info (1)
run: |
echo && apt-cache search "^gcc-" | grep "linux" | sort
- name: apt update & install (2)
run: |
sudo apt-get install ${{ matrix.xcc_pkg }} ${{ matrix.xemu_pkg }}
- name: Environment info (2)
run: |
echo && which $XCC
echo && $XCC --version
echo && $XCC -v # Show built-in specs
echo && which $XEMU
echo && $XEMU --version
- name: ARM (XXH_VECTOR=[ scalar, NEON ])
if: ${{ startsWith(matrix.name, 'ARM') }}
run: |
CPPFLAGS="-DXXH_VECTOR=XXH_SCALAR" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make clean check
CPPFLAGS="-DXXH_VECTOR=XXH_NEON" CFLAGS="-O3 -march=armv7-a -fPIC -mfloat-abi=softfp -mfpu=neon-vfpv4" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make clean check
make -C tests clean
CPPFLAGS="-DXXH_VECTOR=XXH_SCALAR" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make -C tests sanity_test_vectors.h test_sanity
- name: AARCH64 (XXH_VECTOR=[ scalar, NEON, SVE ])
if: ${{ startsWith(matrix.name, 'AARCH64') }}
run: |
CPPFLAGS="-DXXH_VECTOR=XXH_SCALAR" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make clean check
CPPFLAGS="-DXXH_VECTOR=XXH_NEON" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make clean check
CPPFLAGS="-DXXH_VECTOR=XXH_SVE" LDFLAGS="-static" CC="$XCC -march=armv8.2-a+sve" RUN_ENV="$XEMU -cpu max,sve128=on,sve256=off,sve512=off,sve1024=off,sve2048=off" make clean check
CPPFLAGS="-DXXH_VECTOR=XXH_SVE" LDFLAGS="-static" CC="$XCC -march=armv8.2-a+sve" RUN_ENV="$XEMU -cpu max,sve128=on,sve256=on,sve512=off,sve1024=off,sve2048=off" make clean check
CPPFLAGS="-DXXH_VECTOR=XXH_SVE" LDFLAGS="-static" CC="$XCC -march=armv8.2-a+sve" RUN_ENV="$XEMU -cpu max,sve128=on,sve256=on,sve512=on,sve1024=off,sve2048=off" make clean check
CPPFLAGS="-DXXH_VECTOR=XXH_SVE" LDFLAGS="-static" CC="$XCC -march=armv8.2-a+sve" RUN_ENV="$XEMU -cpu max,sve128=on,sve256=on,sve512=on,sve1024=on,sve2048=off" make clean check
CPPFLAGS="-DXXH_VECTOR=XXH_SVE" LDFLAGS="-static" CC="$XCC -march=armv8.2-a+sve" RUN_ENV="$XEMU -cpu max,sve128=on,sve256=on,sve512=on,sve1024=on,sve2048=on" make clean check
- name: PPC64(LE) (XXH_VECTOR=[ scalar, VSX ])
if: ${{ startsWith(matrix.name, 'PPC64') }}
run: |
CPPFLAGS="-DXXH_VECTOR=XXH_SCALAR" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make clean check
CPPFLAGS="-DXXH_VECTOR=XXH_VSX" CFLAGS="-O3 -maltivec -mvsx -mpower8-vector -mcpu=power8" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make clean check
- name: S390X (XXH_VECTOR=[ scalar, VSX ])
if: ${{ startsWith(matrix.name, 'S390X') }}
run: |
CPPFLAGS="-DXXH_VECTOR=XXH_SCALAR" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make clean check
CPPFLAGS=-DXXH_VECTOR=XXH_VSX CFLAGS="-O3 -march=arch11 -mzvector" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make clean check
- name: MIPS-M68K-RISCV-SPARC (XXH_VECTOR=[ scalar ])
if: ${{ startsWith(matrix.name, 'MIPS') || startsWith(matrix.name, 'M68K') || startsWith(matrix.name, 'RISC-V') || startsWith(matrix.name, 'SPARC') }}
run: |
make clean; LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make check
- name: LoongArch (XXH_VECTOR=[ scalar, LSX ])
if: ${{ startsWith(matrix.name, 'LoongArch') }}
run: |
CPPFLAGS="-DXXH_VECTOR=XXH_SCALAR" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make clean check
CPPFLAGS=-DXXH_VECTOR=XXH_LSX CFLAGS="-O3 -march=la464 -mlsx" LDFLAGS="-static" CC=$XCC RUN_ENV=$XEMU make clean check
# macOS
macos-general:
name: ${{ matrix.system.os }}
runs-on: ${{ matrix.system.os }}
strategy:
fail-fast: false # 'false' means Don't stop matrix workflows even if some matrix failed.
matrix:
system: [
{ os: macos-13 },
{ os: macos-14 },
{ os: macos-15 },
{ os: macos-latest },
]
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Environment info
run: |
echo && clang --version
echo && sysctl -a | grep machdep.cpu # cpuinfo
- name: make
run: |
CFLAGS="-Werror" make clean default
- name: make test
run: |
# test scenario where "stdout" is not the console
make clean test MOREFLAGS='-Werror' | tee
# Windows, { VC++2022, VC++2019 } x { x64, Win32, ARM, ARM64 }
#
# - Default shell for Windows environment is PowerShell Core.
# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#using-a-specific-shell
#
# - "windows-2022" uses Visual Studio 2022.
# https://github.com/actions/virtual-environments/blob/main/images/win/Windows2022-Readme.md#visual-studio-enterprise-2022
#
# - "windows-2019" uses Visual Studio 2019.
# https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#visual-studio-enterprise-2019
windows-visualc-general:
name: ${{ matrix.system.vc }}, ${{ matrix.arch }}
runs-on: ${{ matrix.system.os }} # Runs-on foreach value of strategy.matrix.system.os
strategy:
fail-fast: false # 'false' means: Don't stop matrix workflows even if some matrix failed.
matrix:
system: [
{ os: windows-2022, vc: "VC++ 2022", clangcl: 'true', },
{ os: windows-2019, vc: "VC++ 2019", clangcl: 'true', },
]
arch: [ x64, Win32, ARM64 ]
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Build ${{ matrix.system.os }}, ${{ matrix.arch }}
run: |
cd cmake_unofficial
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -A ${{ matrix.arch }} -DCMAKE_C_FLAGS="/W4 /WX"
cmake --build . --config Release
- name: Test
# Run benchmark for testing only if target arch is x64 or Win32.
if: ${{ matrix.arch == 'x64' || matrix.arch == 'Win32' }}
run: |
.\cmake_unofficial\build\Release\xxhsum.exe -bi1
- name: Build ${{ matrix.system.os }}, ${{ matrix.arch }}, with DISPATCH
# DISPATCH only if target arch is x64 or Win32.
if: ${{ ( matrix.arch == 'x64' || matrix.arch == 'Win32' ) }}
run: |
cd cmake_unofficial
mkdir build-visual-dispatch
cd build-visual-dispatch
cmake .. -DCMAKE_BUILD_TYPE=Release -DDISPATCH=ON -A x64 -DCMAKE_C_FLAGS="/W4 /WX"
cmake --build . --config Release
- name: Runtime Test (DISPATCH)
# Run benchmark for testing only if target arch is x64 or Win32.
if: ${{ ( matrix.arch == 'x64' || matrix.arch == 'Win32' ) }}
run: |
.\cmake_unofficial\build-visual-dispatch\Release\xxhsum.exe -V | grep autoVec
.\cmake_unofficial\build-visual-dispatch\Release\xxhsum.exe -bi1
- name: Build ${{ matrix.system.os }}, clang-cl, ${{ matrix.arch }}
if: ${{ matrix.system.clangcl == 'true' }}
run: |
cd cmake_unofficial
mkdir build-clang-cl
cd build-clang-cl
cmake .. -DCMAKE_BUILD_TYPE=Release -A x64 -DCMAKE_GENERATOR_TOOLSET=ClangCL
cmake --build . --config Release
- name: Test (clang-cl)
# Run benchmark for testing only if target arch is x64 or Win32.
if: ${{ matrix.system.clangcl == 'true' && ( matrix.arch == 'x64' || matrix.arch == 'Win32' ) }}
run: |
.\cmake_unofficial\build-clang-cl\Release\xxhsum.exe -bi1
# Windows, { mingw64, mingw32 }
#
# - Shell for msys2 is sh (msys2). defaults.run.shell is for this setting.
#
# https://github.com/msys2/MINGW-packages/blob/master/.github/workflows/main.yml
# https://github.com/actions/starter-workflows/issues/95
windows-msys2-general:
name: Windows ${{ matrix.msystem }}
runs-on: windows-latest
strategy:
fail-fast: false # 'false' means Don't stop matrix workflows even if some matrix failed.
matrix:
include: [
{ msystem: mingw64, toolchain: mingw-w64-x86_64-toolchain },
{ msystem: mingw32, toolchain: mingw-w64-i686-toolchain },
]
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: msys2/setup-msys2@7efe20baefed56359985e327d329042cde2434ff # v2
with:
msystem: MSYS
install: mingw-w64-i686-make ${{ matrix.toolchain }}
update: true
- name: Update
run: |
pacman --noconfirm -Suuy
pacman --noconfirm -Suu
- name: mingw64
if: ${{ matrix.msystem == 'mingw64' }}
run: |
PATH=/mingw64/bin:$PATH /mingw32/bin/mingw32-make clean test gcc-og-test MOREFLAGS=-Werror
PATH=/mingw64/bin:$PATH /mingw32/bin/mingw32-make -C tests/bench
# Abort if result of "file ./xxhsum.exe" doesn't contain 'x86-64'.
# Expected output is "./xxhsum.exe: PE32+ executable (console) x86-64, for MS Windows"
file ./xxhsum.exe
file ./xxhsum.exe | grep -q 'x86-64' || $(exit 1)
./xxhsum.exe --version
- name: mingw32
if: ${{ matrix.msystem == 'mingw32' }}
run: |
PATH=/mingw32/bin:$PATH /mingw32/bin/mingw32-make.exe clean test MOREFLAGS=-Werror
PATH=/mingw32/bin:$PATH /mingw32/bin/mingw32-make.exe -C tests/bench
# Abort if result of "file ./xxhsum.exe" doesn't contain '80386'.
# Expected output is "./xxhsum.exe: PE32 executable (console) Intel i386, for MS Windows"
file ./xxhsum.exe
file ./xxhsum.exe | grep -q '386' || $(exit 1)
./xxhsum.exe --version
+72
View File
@@ -0,0 +1,72 @@
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.
name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: '35 19 * * 2'
push:
branches: [ "dev" ]
# Declare default permissions as read only.
permissions: read-all
jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write
# Uncomment the permissions below if installing in a private repository.
# contents: read
# actions: read
steps:
- name: "Checkout code"
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories:
# - `publish_results` will always be set to `false`, regardless
# of the value entered here.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@c6c77c8c2d62cfd5b2e8d548817fd3d1582ac744 # v2.14.5
with:
sarif_file: results.sarif
+18 -3
View File
@@ -12,14 +12,16 @@ libxxhash.*
xxh32sum
xxh64sum
xxh128sum
xxh3sum
xxhsum
xxhsum32
xxhsum_privateXXH
xxhsum_inlinedXXH
dispatch
tests/generate_unicode_test
# compilation chain
.clang_complete
tests/sanity_test
tests/sanity_test_vectors_generator
fuzzer
# Mac OS-X artefacts
*.dSYM
@@ -44,3 +46,16 @@ infer-out
tmp*
tests/*.unicode
tests/unicode_test*
*.txt
!CMakeLists.txt
*.xxhsum
# editor artifacts
.clang_complete
.clangd
*.swp
.vscode/
.vs/
# Doxygen
doxygen/
-113
View File
@@ -1,113 +0,0 @@
language: c
# Dump CPU info before start
before_install:
- cat /proc/cpuinfo
matrix:
fast_finish: true
include:
- name: General linux tests (Xenial)
dist: xenial
arch: amd64
addons:
apt:
packages:
- clang
- g++-multilib
- gcc-multilib
- cppcheck
script:
- make -B test-all
- name: Check results consistency on x64
arch: amd64
script:
- CPPFLAGS=-DXXH_VECTOR=0 make check # Scalar code path
- make clean
- CPPFLAGS=-DXXH_VECTOR=1 make check # SSE2 code path
- make clean
- CPPFLAGS="-mavx2 -DXXH_VECTOR=2" make check # AVX2 code path
- make clean
- CPPFLAGS=-DXXH_REROLL=1 make check # reroll code path (#240)
- make -C tests/bench
- name: ARM compilation and consistency checks (Qemu)
dist: xenial
arch: amd64
addons:
apt:
packages:
- qemu-system-arm
- qemu-user-static
- gcc-arm-linux-gnueabi
- libc6-dev-armel-cross
script:
# arm (32-bit)
- CC=arm-linux-gnueabi-gcc CPPFLAGS=-DXXH_VECTOR=0 LDFLAGS=-static RUN_ENV=qemu-arm-static make check # Scalar code path
- make clean
# NEON (32-bit)
- CC=arm-linux-gnueabi-gcc CPPFLAGS=-DXXH_VECTOR=3 CFLAGS="-O3 -march=armv7-a -fPIC -mfloat-abi=softfp -mfpu=neon-vfpv4" LDFLAGS=-static RUN_ENV=qemu-arm-static make check # NEON code path
- name: aarch64 compilation and consistency checks
dist: xenial
arch: arm64
script:
# aarch64
- CPPFLAGS=-DXXH_VECTOR=0 LDFLAGS=-static make check # Scalar code path
# NEON (64-bit)
- make clean
- CPPFLAGS=-DXXH_VECTOR=3 LDFLAGS=-static make check # NEON code path
# We need Bionic here because the QEMU versions shipped in the older repos
# do not support POWER8 emulation, and compiling QEMU from source is a pain.
- name: PowerPC + PPC64 compilation and consistency checks (Qemu on Bionic)
dist: bionic
arch: amd64
addons:
apt:
packages:
- qemu-system-ppc
- qemu-user-static
- gcc-powerpc-linux-gnu
- gcc-powerpc64-linux-gnu
- libc6-dev-powerpc-cross
- libc6-dev-ppc64-cross
script:
- CC=powerpc-linux-gnu-gcc RUN_ENV=qemu-ppc-static LDFLAGS=-static make check # Scalar code path
- make clean
- CC=powerpc64-linux-gnu-gcc RUN_ENV=qemu-ppc64-static CPPFLAGS=-DXXH_VECTOR=0 CFLAGS="-O3" LDFLAGS="-static -m64" make check # Scalar code path
- make clean
# VSX code
- CC=powerpc64-linux-gnu-gcc RUN_ENV="qemu-ppc64-static -cpu power8" CFLAGS="-O3 -maltivec -mvsx -mcpu=power8 -mpower8-vector" LDFLAGS="-static -m64" make check # Auto code path
- make clean
- name: PPC64LE compilation and consistency checks
dist: xenial
arch: ppc64le
script:
# Scalar (universal) code path
- CPPFLAGS=-DXXH_VECTOR=0 LDFLAGS=-static make check
# VSX code path (64-bit)
- make clean
- CPPFLAGS=-DXXH_VECTOR=4 CFLAGS="-O3 -maltivec -mvsx -mpower8-vector -mcpu=power8" LDFLAGS="-static" make check
- name: IBM s390x compilation and consistency checks
dist: bionic
arch: s390x
script:
# Scalar (universal) code path
- CPPFLAGS=-DXXH_VECTOR=0 LDFLAGS=-static make check
# s390x code path (64-bit)
- make clean
- CPPFLAGS=-DXXH_VECTOR=4 CFLAGS="-O3 -march=arch11 -mzvector" LDFLAGS="-static" make check
- name: cmake build test
script:
- cd cmake_unofficial
- mkdir build
- cd build
- cmake ..
- make
+73
View File
@@ -1,3 +1,76 @@
v0.8.3
- fix : variant `XXH3_128bits_withSecretandSeed()` could produce an invalid result in some specific set of conditions, #894 by @hltj
- cli : vector extension detected at runtime on x86/x64, enabled by default
- cli : new commands `--filelist` and `--files-from`, by @Ian-Clowes
- cli : XXH3 64-bits GNU format can now be generated and checked (command `-H3`)
- portability: LoongArch SX SIMD extension, by @lrzlin
- portability: can build on AIX, suggested by @likema
- portability: validated for SPARC cpus
v0.8.2
- fix : XXH3 S390x vector implementation (@hzhuang1)
- fix : PowerPC vector compilation with IBM XL compiler (@MaxiBoether)
- perf : improved WASM speed by x2/x3 using SIMD128 (@easyaspi314)
- perf : improved speed (+20%) for XXH3 on ARM NEON (@easyaspi314)
- cli : Fix filename contain /LF character (@t-mat)
- cli : Support # comment lines in --check files (@t-mat)
- cli : Support commands --binary and --ignore-missing (@t-mat)
- build: fix -Og compilation (@easyaspi314, @t-mat)
- build: fix pkgconfig generation with cmake (@ilya-fedin)
- build: fix icc compilation
- build: fix cmake install directories
- build: new build options XXH_NO_XXH3, XXH_SIZE_OPT and XXH_NO_STREAM to reduce binary size (@easyaspi314)
- build: dedicated install targets (@ffontaine)
- build: support DISPATCH mode in cmake (@hzhuang1)
- portability: fix x86dispatch when building with Visual + clang-cl (@t-mat)
- portability: SVE vector implementation of XXH3 (@hzhuang1)
- portability: compatibility with freestanding environments, using XXH_NO_STDLIB
- portability: can build on Haiku (@Begasus)
- portability: validated on m68k and risc-v
- doc : XXH3 specification (@Adrien1018)
- doc : improved doxygen documentation (@easyaspi314, @t-mat)
- misc : dedicated sanity test binary (@t-mat)
v0.8.1
- perf : much improved performance for XXH3 streaming variants, notably on gcc and msvc
- perf : improved XXH64 speed and latency on small inputs
- perf : small XXH32 speed and latency improvement on small inputs of random size
- perf : minor stack usage improvement for XXH32 and XXH64
- api : new experimental variants XXH3_*_withSecretandSeed()
- api : update XXH3_generateSecret(), can no generate secret of any size (>= XXH3_SECRET_SIZE_MIN)
- cli : xxhsum can now generate and check XXH3 checksums, using command `-H3`
- build: can build xxhash without XXH3, with new build macro XXH_NO_XXH3
- build: fix xxh_x86dispatch build with MSVC, by @apankrat
- build: XXH_INLINE_ALL can always be used safely, even after XXH_NAMESPACE or a previous XXH_INLINE_ALL
- build: improved PPC64LE vector support, by @mpe
- install: fix pkgconfig, by @ellert
- install: compatibility with Haiku, by @Begasus
- doc : code comments made compatible with doxygen, by @easyaspi314
- misc : XXH_ACCEPT_NULL_INPUT_POINTER is no longer necessary, all functions can accept NULL input pointers, as long as size == 0
- misc : complete refactor of CI tests on Github Actions, offering much larger coverage, by @t-mat
- misc : xxhsum code base split into multiple specialized units, within directory cli/, by @easyaspi314
v0.8.0
- api : stabilize XXH3
- cli : xxhsum can parse BSD-style --check lines, by @WayneD
- cli : `xxhsum -` accepts console input, requested by @jaki
- cli : xxhsum accepts -- separator, by @jaki
- cli : fix : print correct default algo for symlinked helpers, by @martinetd
- install: improved pkgconfig script, allowing custom install locations, requested by @ellert
v0.7.4
- perf: automatic vector detection and selection at runtime (`xxh_x86dispatch.h`), initiated by @easyaspi314
- perf: added AVX512 support, by @gzm55
- api : new: secret generator `XXH_generateSecret()`, suggested by @koraa
- api : fix: XXH3_state_t is movable, identified by @koraa
- api : fix: state is correctly aligned in AVX mode (unlike `malloc()`), by @easyaspi314
- api : fix: streaming generated wrong values in some combination of random ingestion lengths, reported by @WayneD
- cli : fix unicode print on Windows, by @easyaspi314
- cli : can `-c` check file generated by sfv
- build: `make DISPATCH=1` generates `xxhsum` and `libxxhash` with runtime vector detection (x86/x64 only)
- install: cygwin installation support
- doc : Cryptol specification of XXH32 and XXH64, by @weaversa
v0.7.3
- perf: improved speed for large inputs (~+20%)
- perf: improved latency for small inputs (~10%)
+64
View File
@@ -0,0 +1,64 @@
# Doxygen config for xxHash
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "xxHash"
PROJECT_NUMBER = "0.8.2"
PROJECT_BRIEF = "Extremely fast non-cryptographic hash function"
OUTPUT_DIRECTORY = doxygen
OUTPUT_LANGUAGE = English
# We already separate the internal docs.
INTERNAL_DOCS = NO
# Consistency
SORT_MEMBER_DOCS = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
# Warnings
QUIET = YES
# Until we document everything
WARN_IF_UNDOCUMENTED = NO
# TODO: Add the other files. It is just xxhash.h for now.
FILE_PATTERNS = xxhash.h xxh_x86dispatch.c
# Note: xxHash's source files are technically ASCII only.
INPUT_ENCODING = UTF-8
TAB_SIZE = 4
MARKDOWN_SUPPORT = YES
# xxHash is a C library
OPTIMIZE_OUTPUT_FOR_C = YES
# We hide private part from public document
EXTRACT_STATIC = NO
# We hide private part from public document
EXTRACT_PRIVATE = NO
# Document the macros
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
# Predefine some macros to clean up the output.
PREDEFINED = "XXH_DOXYGEN=" \
"XXH_PUBLIC_API=" \
"XXH_NOESCAPE=" \
"XXH_FORCE_INLINE=static inline" \
"XXH_NO_INLINE=static" \
"XXH_RESTRICT=restrict" \
"XSUM_API=" \
"XXH_STATIC_LINKING_ONLY" \
"XXH_IMPLEMENTATION" \
"XXH_PUREF=[[gnu::pure]]" \
"XXH_CONSTF=[[gnu::const]]" \
"XXH_MALLOCF=[[gnu::malloc]]" \
"XXH_ALIGN(N)=alignas(N)" \
"XXH_ALIGN_MEMBER(align,type)=alignas(align) type"
# We want HTML docs
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
# Tweak the colors a bit
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_GAMMA = 100
HTML_COLORSTYLE_SAT = 100
# We don't want LaTeX.
GENERATE_LATEX = NO
+64
View File
@@ -0,0 +1,64 @@
# Doxygen config for xxHash
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "xxHash"
PROJECT_NUMBER = "0.8.2"
PROJECT_BRIEF = "Extremely fast non-cryptographic hash function"
OUTPUT_DIRECTORY = doxygen
OUTPUT_LANGUAGE = English
# We already separate the internal docs.
INTERNAL_DOCS = YES
# Consistency
SORT_MEMBER_DOCS = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
# Warnings
QUIET = YES
# Until we document everything
WARN_IF_UNDOCUMENTED = NO
# TODO: Add the other files. It is just xxhash.h for now.
FILE_PATTERNS = xxhash.h xxh_x86dispatch.c
# Note: xxHash's source files are technically ASCII only.
INPUT_ENCODING = UTF-8
TAB_SIZE = 4
MARKDOWN_SUPPORT = YES
# xxHash is a C library
OPTIMIZE_OUTPUT_FOR_C = YES
# So we can document the internals
EXTRACT_STATIC = YES
# We show private part in the internal document
EXTRACT_PRIVATE = YES
# Document the macros
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
# Predefine some macros to clean up the output.
PREDEFINED = "XXH_DOXYGEN=" \
"XXH_PUBLIC_API=" \
"XXH_NOESCAPE=" \
"XXH_FORCE_INLINE=static inline" \
"XXH_NO_INLINE=static" \
"XXH_RESTRICT=restrict" \
"XSUM_API=" \
"XXH_STATIC_LINKING_ONLY" \
"XXH_IMPLEMENTATION" \
"XXH_PUREF=[[gnu::pure]]" \
"XXH_CONSTF=[[gnu::const]]" \
"XXH_MALLOCF=[[gnu::malloc]]" \
"XXH_ALIGN(N)=alignas(N)" \
"XXH_ALIGN_MEMBER(align,type)=alignas(align) type"
# We want HTML docs
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
# Tweak the colors a bit
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_GAMMA = 100
HTML_COLORSTYLE_SAT = 100
# We don't want LaTeX.
GENERATE_LATEX = NO
+1 -23
View File
@@ -1,5 +1,5 @@
xxHash Library
Copyright (c) 2012-present, Yann Collet
Copyright (c) 2012-2021 Yann Collet
All rights reserved.
BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
@@ -24,25 +24,3 @@ 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.
----------------------------------------------------
xxhsum command line interface
Copyright (c) 2013-present, Yann Collet
All rights reserved.
GPL v2 License
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+387 -105
View File
@@ -1,6 +1,6 @@
# ################################################################
# xxHash Makefile
# Copyright (C) Yann Collet 2012-present
# Copyright (C) 2012-2024 Yann Collet
#
# GPL v2 License
#
@@ -24,11 +24,14 @@
# ################################################################
# xxhsum: provides 32/64 bits hash of one or multiple files, or stdin
# ################################################################
Q = $(if $(filter 1,$(V) $(VERBOSE)),,@)
# Version numbers
LIBVER_MAJOR_SCRIPT:=`sed -n '/define XXH_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < xxhash.h`
LIBVER_MINOR_SCRIPT:=`sed -n '/define XXH_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < xxhash.h`
LIBVER_PATCH_SCRIPT:=`sed -n '/define XXH_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < xxhash.h`
SED ?= sed
SED_ERE_OPT ?= -E
LIBVER_MAJOR_SCRIPT:=`$(SED) -n '/define XXH_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < xxhash.h`
LIBVER_MINOR_SCRIPT:=`$(SED) -n '/define XXH_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < xxhash.h`
LIBVER_PATCH_SCRIPT:=`$(SED) -n '/define XXH_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < xxhash.h`
LIBVER_MAJOR := $(shell echo $(LIBVER_MAJOR_SCRIPT))
LIBVER_MINOR := $(shell echo $(LIBVER_MINOR_SCRIPT))
LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT))
@@ -40,9 +43,10 @@ DEBUGFLAGS+=-Wall -Wextra -Wconversion -Wcast-qual -Wcast-align -Wshadow \
-Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \
-Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \
-Wredundant-decls -Wstrict-overflow=2
CFLAGS += $(DEBUGFLAGS)
FLAGS = $(CFLAGS) $(CPPFLAGS) $(MOREFLAGS)
CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS)
FLAGS = $(CFLAGS) $(CPPFLAGS)
XXHSUM_VERSION = $(LIBVER)
UNAME := $(shell uname)
# Define *.exe as extension for Windows systems
ifneq (,$(filter Windows%,$(OS)))
@@ -51,9 +55,23 @@ else
EXT =
endif
# automatically enable runtime vector dispatch on x86/64 targets
detect_x86_arch = $(shell $(CC) -dumpmachine | grep -E 'i[3-6]86|x86_64')
ifneq ($(strip $(call detect_x86_arch)),)
#note: can be overridden at compile time, by setting DISPATCH=0
DISPATCH ?= 1
endif
ifeq ($(NODE_JS),1)
# Link in unrestricted filesystem support
LDFLAGS += -sNODERAWFS
# Set flag to fix isatty() support
CPPFLAGS += -DXSUM_NODE_JS=1
endif
# OS X linker doesn't support -soname, and use different extension
# see: https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html
ifeq ($(shell uname), Darwin)
ifeq ($(UNAME), Darwin)
SHARED_EXT = dylib
SHARED_EXT_MAJOR = $(LIBVER_MAJOR).$(SHARED_EXT)
SHARED_EXT_VER = $(LIBVER).$(SHARED_EXT)
@@ -67,36 +85,60 @@ endif
LIBXXH = libxxhash.$(SHARED_EXT_VER)
XXHSUM_SRC_DIR = cli
XXHSUM_SPLIT_SRCS = $(XXHSUM_SRC_DIR)/xxhsum.c \
$(XXHSUM_SRC_DIR)/xsum_os_specific.c \
$(XXHSUM_SRC_DIR)/xsum_arch.c \
$(XXHSUM_SRC_DIR)/xsum_output.c \
$(XXHSUM_SRC_DIR)/xsum_sanity_check.c \
$(XXHSUM_SRC_DIR)/xsum_bench.c
XXHSUM_SPLIT_OBJS = $(XXHSUM_SPLIT_SRCS:.c=.o)
XXHSUM_HEADERS = $(XXHSUM_SRC_DIR)/xsum_config.h \
$(XXHSUM_SRC_DIR)/xsum_arch.h \
$(XXHSUM_SRC_DIR)/xsum_os_specific.h \
$(XXHSUM_SRC_DIR)/xsum_output.h \
$(XXHSUM_SRC_DIR)/xsum_sanity_check.h \
$(XXHSUM_SRC_DIR)/xsum_bench.h
## generate CLI and libraries in release mode (default for `make`)
.PHONY: default
default: ## generate CLI and libraries in release mode (default for `make`)
default: DEBUGFLAGS=
default: lib xxhsum_and_links
.PHONY: all
all: lib xxhsum xxhsum_inlinedXXH
xxhsum: xxhash.o xxhsum.o ## generate command line interface (CLI)
## xxhsum is the command line interface (CLI)
ifeq ($(DISPATCH),1)
xxhsum: CPPFLAGS += -DXXHSUM_DISPATCH=1
xxhsum: xxh_x86dispatch.o
endif
xxhsum: xxhash.o $(XXHSUM_SPLIT_OBJS)
$(CC) $(FLAGS) $^ $(LDFLAGS) -o $@$(EXT)
xxhsum32: CFLAGS += -m32 ## generate CLI in 32-bits mode
xxhsum32: xxhash.c xxhsum.c ## do not generate object (avoid mixing different ABI)
xxhsum32: xxhash.c $(XXHSUM_SPLIT_SRCS) ## do not generate object (avoid mixing different ABI)
$(CC) $(FLAGS) $^ $(LDFLAGS) -o $@$(EXT)
xxhash.o: xxhash.c xxhash.h xxh3.h
$(CC) $(FLAGS) -c $< -o $@
xxhsum.o: xxhsum.c xxhash.h
$(CC) $(FLAGS) -c $< -o $@
## dispatch only works for x86/x64 systems
dispatch: CPPFLAGS += -DXXHSUM_DISPATCH=1
dispatch: xxhash.o xxh_x86dispatch.o $(XXHSUM_SPLIT_SRCS)
$(CC) $(FLAGS) $^ $(LDFLAGS) -o $@$(EXT)
xxhash.o: xxhash.c xxhash.h
xxhsum.o: $(XXHSUM_SRC_DIR)/xxhsum.c $(XXHSUM_HEADERS) \
xxhash.h xxh_x86dispatch.h
xxh_x86dispatch.o: xxh_x86dispatch.c xxh_x86dispatch.h xxhash.h
.PHONY: xxhsum_and_links
xxhsum_and_links: xxhsum xxh32sum xxh64sum xxh128sum
xxhsum_and_links: xxhsum xxh32sum xxh64sum xxh128sum xxh3sum
xxh32sum xxh64sum xxh128sum: xxhsum
xxh32sum xxh64sum xxh128sum xxh3sum: xxhsum
ln -sf $<$(EXT) $@$(EXT)
xxhsum_inlinedXXH: CPPFLAGS += -DXXH_INLINE_ALL
xxhsum_inlinedXXH: xxhsum.c
$(CC) $(FLAGS) $^ -o $@$(EXT)
xxhsum_inlinedXXH: $(XXHSUM_SPLIT_SRCS)
$(CC) $(FLAGS) $< -o $@$(EXT)
# library
@@ -109,6 +151,9 @@ $(LIBXXH): LDFLAGS += -shared
ifeq (,$(filter Windows%,$(OS)))
$(LIBXXH): CFLAGS += -fPIC
endif
ifeq ($(LIBXXH_DISPATCH),1)
$(LIBXXH): xxh_x86dispatch.c
endif
$(LIBXXH): xxhash.c
$(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@
ln -sf $@ libxxhash.$(SHARED_EXT_MAJOR)
@@ -122,33 +167,35 @@ libxxhash: $(LIBXXH)
lib: ## generate static and dynamic xxhash libraries
lib: libxxhash.a libxxhash
pkgconfig:
@sed -e 's|@PREFIX@|$(PREFIX)|' \
-e 's|@VERSION@|$(LIBVER)|' \
libxxhash.pc.in >libxxhash.pc
# helper targets
AWK = awk
AWK = awk
GREP = grep
SORT = sort
NM = nm
.PHONY: list
list: ## list all Makefile targets
@$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | $(AWK) -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | $(SORT) | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs
$(Q)$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | $(AWK) -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | $(SORT) | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs
.PHONY: help
help: ## list documented targets
@$(GREP) -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
$(Q)$(GREP) -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
$(SORT) | \
$(AWK) 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
.PHONY: clean
clean: ## remove all build artifacts
@$(RM) -r *.dSYM # Mac OS-X specific
@$(RM) core *.o *.$(SHARED_EXT) *.$(SHARED_EXT).* *.a libxxhash.pc
@$(RM) xxhsum$(EXT) xxhsum32$(EXT) xxhsum_inlinedXXH$(EXT)
@$(RM) xxh32sum$(EXT) xxh64sum$(EXT) xxh128sum$(EXT)
$(Q)$(RM) -r *.dSYM # Mac OS-X specific
$(Q)$(RM) core *.o *.obj *.$(SHARED_EXT) *.$(SHARED_EXT).* *.a libxxhash.pc
$(Q)$(RM) xxhsum$(EXT) xxhsum32$(EXT) xxhsum_inlinedXXH$(EXT) dispatch$(EXT)
$(Q)$(RM) xxhsum.wasm xxhsum.js xxhsum.html
$(Q)$(RM) xxh32sum$(EXT) xxh64sum$(EXT) xxh128sum$(EXT) xxh3sum$(EXT)
$(Q)$(RM) fuzzer
$(Q)$(RM) $(XXHSUM_SRC_DIR)/*.o $(XXHSUM_SRC_DIR)/*.obj
$(MAKE) -C tests clean
$(MAKE) -C tests/bench clean
$(MAKE) -C tests/collisions clean
@echo cleaning completed
@@ -159,63 +206,147 @@ clean: ## remove all build artifacts
# make check can be run with cross-compiled binaries on emulated environments (qemu user mode)
# by setting $(RUN_ENV) to the target emulation environment
.PHONY: check
check: xxhsum ## basic tests for xxhsum CLI, set RUN_ENV for emulated environments
check: xxhsum test_sanity ## basic tests for xxhsum CLI, set RUN_ENV for emulated environments
# stdin
# If you get "Wrong parameters" on Emscripten+Node.js, recompile with `NODE_JS=1`
$(RUN_ENV) ./xxhsum$(EXT) < xxhash.c
# multiple files
$(RUN_ENV) ./xxhsum$(EXT) xxhash.* xxhsum.*
$(RUN_ENV) ./xxhsum$(EXT) xxhash.*
# internal bench
$(RUN_ENV) ./xxhsum$(EXT) -bi1
$(RUN_ENV) ./xxhsum$(EXT) -bi0
# long bench command
$(RUN_ENV) ./xxhsum$(EXT) --benchmark-all -i0
# bench multiple variants
$(RUN_ENV) ./xxhsum$(EXT) -b1,2,3 -i0
# file bench
$(RUN_ENV) ./xxhsum$(EXT) -bi1 xxhash.c
$(RUN_ENV) ./xxhsum$(EXT) -bi0 xxhash.c
# 32-bit
$(RUN_ENV) ./xxhsum$(EXT) -H0 xxhash.c
# 128-bit
$(RUN_ENV) ./xxhsum$(EXT) -H2 xxhash.c
# XXH3 (enforce BSD style)
$(RUN_ENV) ./xxhsum$(EXT) -H3 xxhash.c | grep "XXH3"
# request incorrect variant
$(RUN_ENV) ./xxhsum$(EXT) -H9 xxhash.c ; test $$? -eq 1
@printf "\n ....... checks completed successfully ....... \n"
.PHONY: test-unicode
test-unicode:
$(MAKE) -C tests test_unicode
.PHONY: test_sanity
test_sanity:
$(MAKE) -C tests test_sanity
.PHONY: test-mem
VALGRIND = valgrind --leak-check=yes --error-exitcode=1
test-mem: RUN_ENV = $(VALGRIND)
test-mem: xxhsum check
.PHONY: test32
test32: clean xxhsum32
test32: xxhsum32
@echo ---- test 32-bit ----
./xxhsum32 -bi1 xxhash.c
./xxhsum32 -bi0 xxhash.c
TEST_FILES = xxhsum$(EXT) xxhash.c xxhash.h
.PHONY: test-xxhsum-c
test-xxhsum-c: xxhsum
# xxhsum to/from pipe
./xxhsum xxh* | ./xxhsum -c -
./xxhsum -H0 xxh* | ./xxhsum -c -
./xxhsum $(TEST_FILES) | ./xxhsum -c -
./xxhsum -H0 $(TEST_FILES) | ./xxhsum -c -
# xxhsum -c is unable to verify checksum of file from STDIN (#470)
./xxhsum < README.md > .test.README.md.xxh
./xxhsum -c .test.README.md.xxh < README.md
# xxhsum -q does not display "Loading" message into stderr (#251)
! ./xxhsum -q xxh* 2>&1 | grep Loading
! ./xxhsum -q $(TEST_FILES) 2>&1 | grep Loading
# xxhsum does not display "Loading" message into stderr either
! ./xxhsum $(TEST_FILES) 2>&1 | grep Loading
# Check that xxhsum do display filename that it failed to open.
LC_ALL=C ./xxhsum nonexistent 2>&1 | grep "Error: Could not open 'nonexistent'"
# xxhsum to/from file, shell redirection
./xxhsum xxh* > .test.xxh64
./xxhsum -H0 xxh* > .test.xxh32
./xxhsum -H2 xxh* > .test.xxh128
./xxhsum -c .test.xxh64
./xxhsum -c .test.xxh32
./xxhsum -c .test.xxh128
./xxhsum $(TEST_FILES) > .test.xxh64
./xxhsum --tag $(TEST_FILES) > .test.xxh64_tag
./xxhsum --little-endian $(TEST_FILES) > .test.le_xxh64
./xxhsum --tag --little-endian $(TEST_FILES) > .test.le_xxh64_tag
./xxhsum -H0 $(TEST_FILES) > .test.xxh32
./xxhsum -H0 --tag $(TEST_FILES) > .test.xxh32_tag
./xxhsum -H0 --little-endian $(TEST_FILES) > .test.le_xxh32
./xxhsum -H0 --tag --little-endian $(TEST_FILES) > .test.le_xxh32_tag
./xxhsum -H2 $(TEST_FILES) > .test.xxh128
./xxhsum -H2 --tag $(TEST_FILES) > .test.xxh128_tag
./xxhsum -H2 --little-endian $(TEST_FILES) > .test.le_xxh128
./xxhsum -H2 --tag --little-endian $(TEST_FILES) > .test.le_xxh128_tag
./xxhsum -H3 $(TEST_FILES) > .test.xxh3
./xxhsum -H3 --tag $(TEST_FILES) > .test.xxh3_tag
./xxhsum -H3 --little-endian $(TEST_FILES) > .test.le_xxh3
./xxhsum -H3 --tag --little-endian $(TEST_FILES) > .test.le_xxh3_tag
./xxhsum -c .test.xxh*
./xxhsum -c --little-endian .test.le_xxh*
./xxhsum -c .test.*_tag
# read list of files from stdin
./xxhsum -c < .test.xxh64
./xxhsum -c < .test.xxh32
./xxhsum -c < .test.xxh64
./xxhsum -c < .test.xxh128
./xxhsum -c < .test.xxh3
cat .test.xxh* | ./xxhsum -c -
# check variant with '*' marker as second separator
$(SED) 's/ / \*/' .test.xxh32 | ./xxhsum -c
# bsd-style output
./xxhsum --tag xxhsum* | $(GREP) XXH64
./xxhsum --tag -H0 xxhsum* | $(GREP) XXH32
./xxhsum --tag -H1 xxhsum* | $(GREP) XXH64
./xxhsum --tag -H2 xxhsum* | $(GREP) XXH128
./xxhsum --tag -H3 xxhsum* | $(GREP) XXH3
./xxhsum -H3 xxhsum* | $(GREP) XXH3_ # prefix for GNU format
./xxhsum --tag -H32 xxhsum* | $(GREP) XXH32
./xxhsum --tag -H64 xxhsum* | $(GREP) XXH64
./xxhsum --tag -H128 xxhsum* | $(GREP) XXH128
./xxhsum --tag -H0 --little-endian xxhsum* | $(GREP) XXH32_LE
./xxhsum --tag -H1 --little-endian xxhsum* | $(GREP) XXH64_LE
./xxhsum --tag -H2 --little-endian xxhsum* | $(GREP) XXH128_LE
./xxhsum --tag -H3 --little-endian xxhsum* | $(GREP) XXH3_LE
./xxhsum --tag -H32 --little-endian xxhsum* | $(GREP) XXH32_LE
./xxhsum --tag -H64 --little-endian xxhsum* | $(GREP) XXH64_LE
./xxhsum --tag -H128 --little-endian xxhsum* | $(GREP) XXH128_LE
# check bsd-style
./xxhsum --tag xxhsum* | ./xxhsum -c
./xxhsum --tag -H32 --little-endian xxhsum* | ./xxhsum -c
# xxhsum -c warns improperly format lines.
cat .test.xxh64 .test.xxh32 | ./xxhsum -c - | $(GREP) improperly
cat .test.xxh32 .test.xxh64 | ./xxhsum -c - | $(GREP) improperly
echo '12345678 ' >>.test.xxh32
./xxhsum -c .test.xxh32 | $(GREP) improperly
echo '123456789 file' >>.test.xxh64
./xxhsum -c .test.xxh64 | $(GREP) improperly
# Expects "FAILED"
echo "0000000000000000 LICENSE" | ./xxhsum -c -; test $$? -eq 1
echo "00000000 LICENSE" | ./xxhsum -c -; test $$? -eq 1
# Expects "FAILED open or read"
echo "0000000000000000 test-expects-file-not-found" | ./xxhsum -c -; test $$? -eq 1
echo "00000000 test-expects-file-not-found" | ./xxhsum -c -; test $$? -eq 1
@$(RM) .test.xxh32 .test.xxh64 .test.xxh128
# --filelist
echo xxhash.c > .test.filenames
$(RUN_ENV) ./xxhsum$(EXT) --filelist .test.filenames
# --filelist from stdin
cat .test.filenames | $(RUN_ENV) ./xxhsum$(EXT) --filelist
@$(RM) .test.*
LIB_FUZZING_ENGINE?="-fsanitize=fuzzer"
CC_VERSION := $(shell $(CC) --version)
ifneq (,$(findstring clang,$(CC_VERSION)))
fuzzer: libxxhash.a fuzz/fuzzer.c
$(CC) $(CFLAGS) $(LIB_FUZZING_ENGINE) -I. -o fuzzer fuzz/fuzzer.c -L. -Wl,-Bstatic -lxxhash -Wl,-Bdynamic
endif
.PHONY: test-filename-escape
test-filename-escape:
$(MAKE) -C tests test_filename_escape
.PHONY: test-cli-comment-line
test-cli-comment-line:
$(MAKE) -C tests test_cli_comment_line
.PHONY: test-cli-ignore-missing
test-cli-ignore-missing:
$(MAKE) -C tests test_cli_ignore_missing
.PHONY: armtest
armtest: clean
@@ -227,11 +358,18 @@ clangtest: clean
@echo ---- test clang compilation ----
CC=clang MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion" $(MAKE) all
.PHONY: gcc-og-test
gcc-og-test: clean
@echo ---- test gcc -Og compilation ----
CFLAGS="-Og -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror -fPIC" CPPFLAGS="-DXXH_NO_INLINE_HINTS" MOREFLAGS="-Werror" $(MAKE) all
.PHONY: cxxtest
cxxtest: clean
@echo ---- test C++ compilation ----
CC="$(CXX) -Wno-deprecated" $(MAKE) all CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror -fPIC"
# In strict C90 mode, there is no `long long` type support,
# consequently, only XXH32 can be compiled.
.PHONY: c90test
ifeq ($(NO_C90_TEST),true)
c90test:
@@ -242,10 +380,41 @@ c90test: CFLAGS += -std=c90 -Werror -pedantic
c90test: xxhash.c
@echo ---- test strict C90 compilation [xxh32 only] ----
$(RM) xxhash.o
$(CC) $(FLAGS) $^ $(LDFLAGS) -c
$(CC) $(FLAGS) $^ -c
$(NM) xxhash.o | $(GREP) XXH64 ; test $$? -eq 1
$(RM) xxhash.o
endif
.PHONY: noxxh3test
noxxh3test: CPPFLAGS += -DXXH_NO_XXH3
noxxh3test: CFLAGS += -Werror -pedantic -Wno-long-long # XXH64 requires long long support
noxxh3test: OFILE = xxh_noxxh3.o
noxxh3test: xxhash.c
@echo ---- test compilation without XXH3 ----
$(CC) $(FLAGS) -c $^ -o $(OFILE)
$(NM) $(OFILE) | $(GREP) XXH3_ ; test $$? -eq 1
$(RM) $(OFILE)
.PHONY: nostreamtest
nostreamtest: CPPFLAGS += -DXXH_NO_STREAM
nostreamtest: CFLAGS += -Werror -pedantic -Wno-long-long # XXH64 requires long long support
nostreamtest: OFILE = xxh_nostream.o
nostreamtest: xxhash.c
@echo ---- test compilation without streaming ----
$(CC) $(FLAGS) -c $^ -o $(OFILE)
$(NM) $(OFILE) | $(GREP) update ; test $$? -eq 1
$(RM) $(OFILE)
.PHONY: nostdlibtest
nostdlibtest: CPPFLAGS += -DXXH_NO_STDLIB
nostdlibtest: CFLAGS += -Werror -pedantic -Wno-long-long # XXH64 requires long long support
nostdlibtest: OFILE = xxh_nostdlib.o
nostdlibtest: xxhash.c
@echo ---- test compilation without \<stdlib.h\> ----
$(CC) $(FLAGS) -c $^ -o $(OFILE)
$(NM) $(OFILE) | $(GREP) "U _free\|U free" ; test $$? -eq 1
$(RM) $(OFILE)
.PHONY: usan
usan: CC=clang
usan: CXX=clang++
@@ -270,16 +439,17 @@ cppcheck: ## check C source files using $(CPPCHECK) static analyzer
namespaceTest: ## ensure XXH_NAMESPACE redefines all public symbols
$(CC) -c xxhash.c
$(CC) -DXXH_NAMESPACE=TEST_ -c xxhash.c -o xxhash2.o
$(CC) xxhash.o xxhash2.o xxhsum.c -o xxhsum2 # will fail if one namespace missing (symbol collision)
$(CC) xxhash.o xxhash2.o $(XXHSUM_SPLIT_SRCS) -o xxhsum2 # will fail if one namespace missing (symbol collision)
$(RM) *.o xxhsum2 # clean
MAN = $(XXHSUM_SRC_DIR)/xxhsum.1
MD2ROFF ?= ronn
MD2ROFF_FLAGS ?= --roff --warnings --manual="User Commands" --organization="xxhsum $(XXHSUM_VERSION)"
xxhsum.1: xxhsum.1.md xxhash.h
cat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | sed -n '/^\.\\\".*/!p' > $@
$(MAN): $(XXHSUM_SRC_DIR)/xxhsum.1.md xxhash.h
cat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | $(SED) -n '/^\.\\\".*/!p' > $@
.PHONY: man
man: xxhsum.1 ## generate man page from markdown source
man: $(MAN) ## generate man page from markdown source
.PHONY: clean-man
clean-man:
@@ -290,21 +460,69 @@ preview-man: man
man ./xxhsum.1
.PHONY: test
test: DEBUGFLAGS += -DDEBUGLEVEL=1
test: all namespaceTest check test-xxhsum-c c90test test-tools
test: DEBUGFLAGS += -DXXH_DEBUGLEVEL=1
test: all namespaceTest check test-xxhsum-c c90test test-tools noxxh3test nostdlibtest
# this test checks that including "xxhash.h" multiple times and with different directives still compiles properly
.PHONY: test-multiInclude
test-multiInclude:
$(MAKE) -C tests test_multiInclude
.PHONY: test-inline-notexposed
test-inline-notexposed: xxhsum_inlinedXXH
$(NM) xxhsum_inlinedXXH | $(GREP) "t _XXH32_" ; test $$? -eq 1 # no XXH32 symbol should be left
$(NM) xxhsum_inlinedXXH | $(GREP) "t _XXH64_" ; test $$? -eq 1 # no XXH64 symbol should be left
.PHONY: test-inline
test-inline:
$(MAKE) -C tests test_multiInclude
test-inline: test-inline-notexposed test-multiInclude
.PHONY: test-all
test-all: CFLAGS += -Werror
test-all: test test32 clangtest cxxtest usan test-inline listL120 trailingWhitespace staticAnalyze test-unicode
test-all: test test32 test-unicode clangtest gcc-og-test cxxtest usan test-inline listL120 trailingWhitespace test-xxh-nnn-sums
.PHONY: test-tools
test-tools:
CFLAGS=-Werror $(MAKE) -C tests/bench
CFLAGS=-Werror $(MAKE) -C tests/collisions
CFLAGS=-Werror $(MAKE) -C tests/collisions check
.PHONY: test-xxh-nnn-sums
test-xxh-nnn-sums: xxhsum_and_links
./xxhsum README.md > tmp.xxhsum.out # xxhsum outputs xxh64
./xxh32sum README.md > tmp.xxh32sum.out
./xxh64sum README.md > tmp.xxh64sum.out
./xxh128sum README.md > tmp.xxh128sum.out
./xxh3sum README.md > tmp.xxh3sum.out
cat tmp.xxhsum.out
cat tmp.xxh32sum.out
cat tmp.xxh64sum.out
cat tmp.xxh128sum.out
cat tmp.xxh3sum.out
./xxhsum -c tmp.xxhsum.out
./xxhsum -c tmp.xxh32sum.out
./xxhsum -c tmp.xxh64sum.out
./xxhsum -c tmp.xxh128sum.out
./xxhsum -c tmp.xxh3sum.out
./xxh32sum -c tmp.xxhsum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh32sum -c tmp.xxh32sum.out
./xxh32sum -c tmp.xxh64sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh32sum -c tmp.xxh128sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh32sum -c tmp.xxh3sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh64sum -c tmp.xxhsum.out
./xxh64sum -c tmp.xxh32sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh64sum -c tmp.xxh64sum.out
./xxh64sum -c tmp.xxh128sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh64sum -c tmp.xxh3sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh128sum -c tmp.xxhsum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh128sum -c tmp.xxh32sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh128sum -c tmp.xxh64sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh128sum -c tmp.xxh128sum.out
./xxh128sum -c tmp.xxh3sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh3sum -c tmp.xxhsum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh3sum -c tmp.xxh32sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh3sum -c tmp.xxh64sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh3sum -c tmp.xxh128sum.out ; test $$? -eq 1 # expects "no properly formatted"
./xxh3sum -c tmp.xxh3sum.out
.PHONY: listL120
listL120: # extract lines >= 120 characters in *.{c,h}, by Takayuki Matsuoka (note: $$, for Makefile compatibility)
@@ -312,13 +530,16 @@ listL120: # extract lines >= 120 characters in *.{c,h}, by Takayuki Matsuoka (n
.PHONY: trailingWhitespace
trailingWhitespace:
! $(GREP) -E "`printf '[ \\t]$$'`" xxhsum.1 *.c *.h LICENSE Makefile cmake_unofficial/CMakeLists.txt
! $(GREP) -E "`printf '[ \\t]$$'`" cli/*.c cli/*.h cli/*.1 *.c *.h LICENSE Makefile cmake_unofficial/CMakeLists.txt
.PHONY: lint-unicode
lint-unicode:
./tests/unicode_lint.sh
# =========================================================
# make install is validated only for the following targets
# =========================================================
ifneq (,$(filter $(shell uname),Linux Darwin GNU/kFreeBSD GNU OpenBSD FreeBSD NetBSD DragonFly SunOS))
ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU Haiku OpenBSD FreeBSD NetBSD DragonFly SunOS CYGWIN% , $(UNAME)))
DESTDIR ?=
# directory variables: GNU conventions prefer lowercase
@@ -327,29 +548,30 @@ DESTDIR ?=
prefix ?= /usr/local
PREFIX ?= $(prefix)
exec_prefix ?= $(PREFIX)
libdir ?= $(exec_prefix)/lib
EXEC_PREFIX ?= $(exec_prefix)
libdir ?= $(EXEC_PREFIX)/lib
LIBDIR ?= $(libdir)
includedir ?= $(PREFIX)/include
INCLUDEDIR ?= $(includedir)
bindir ?= $(exec_prefix)/bin
bindir ?= $(EXEC_PREFIX)/bin
BINDIR ?= $(bindir)
datarootdir ?= $(PREFIX)/share
mandir ?= $(datarootdir)/man
man1dir ?= $(mandir)/man1
ifneq (,$(filter $(shell uname),FreeBSD NetBSD DragonFly))
ifneq (,$(filter $(UNAME),FreeBSD NetBSD DragonFly))
PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig
else
PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig
endif
ifneq (,$(filter $(shell uname),OpenBSD FreeBSD NetBSD DragonFly SunOS))
ifneq (,$(filter $(UNAME),OpenBSD FreeBSD NetBSD DragonFly SunOS))
MANDIR ?= $(PREFIX)/man/man1
else
MANDIR ?= $(man1dir)
endif
ifneq (,$(filter $(shell uname),SunOS))
ifneq (,$(filter $(UNAME),SunOS))
INSTALL ?= ginstall
else
INSTALL ?= install
@@ -357,51 +579,111 @@ endif
INSTALL_PROGRAM ?= $(INSTALL)
INSTALL_DATA ?= $(INSTALL) -m 644
MAKE_DIR ?= $(INSTALL) -d -m 755
# Escape special symbols by putting each character into its separate class
EXEC_PREFIX_REGEX ?= $(shell echo "$(EXEC_PREFIX)" | $(SED) $(SED_ERE_OPT) -e "s/([^^])/[\1]/g" -e "s/\\^/\\\\^/g")
PREFIX_REGEX ?= $(shell echo "$(PREFIX)" | $(SED) $(SED_ERE_OPT) -e "s/([^^])/[\1]/g" -e "s/\\^/\\\\^/g")
PCLIBDIR ?= $(shell echo "$(LIBDIR)" | $(SED) -n $(SED_ERE_OPT) -e "s@^$(EXEC_PREFIX_REGEX)(/|$$)@@p")
PCINCDIR ?= $(shell echo "$(INCLUDEDIR)" | $(SED) -n $(SED_ERE_OPT) -e "s@^$(PREFIX_REGEX)(/|$$)@@p")
PCEXECDIR?= $(if $(filter $(PREFIX),$(EXEC_PREFIX)),$$\{prefix\},$(EXEC_PREFIX))
ifeq (,$(PCLIBDIR))
# Additional prefix check is required, since the empty string is technically a
# valid PCLIBDIR
ifeq (,$(shell echo "$(LIBDIR)" | $(SED) -n $(SED_ERE_OPT) -e "\\@^$(EXEC_PREFIX_REGEX)(/|$$)@ p"))
$(error configured libdir ($(LIBDIR)) is outside of exec_prefix ($(EXEC_PREFIX)), can't generate pkg-config file)
endif
endif
ifeq (,$(PCINCDIR))
# Additional prefix check is required, since the empty string is technically a
# valid PCINCDIR
ifeq (,$(shell echo "$(INCLUDEDIR)" | $(SED) -n $(SED_ERE_OPT) -e "\\@^$(PREFIX_REGEX)(/|$$)@ p"))
$(error configured includedir ($(INCLUDEDIR)) is outside of prefix ($(PREFIX)), can't generate pkg-config file)
endif
endif
libxxhash.pc: libxxhash.pc.in
@echo creating pkgconfig
$(Q)$(SED) $(SED_ERE_OPT) -e 's|@PREFIX@|$(PREFIX)|' \
-e 's|@EXECPREFIX@|$(PCEXECDIR)|' \
-e 's|@LIBDIR@|$$\{exec_prefix\}/$(PCLIBDIR)|' \
-e 's|@INCLUDEDIR@|$$\{prefix\}/$(PCINCDIR)|' \
-e 's|@VERSION@|$(LIBVER)|' \
$< > $@
install_libxxhash.a: libxxhash.a
@echo Installing libxxhash.a
$(Q)$(MAKE_DIR) $(DESTDIR)$(LIBDIR)
$(Q)$(INSTALL_DATA) libxxhash.a $(DESTDIR)$(LIBDIR)
install_libxxhash: libxxhash
@echo Installing libxxhash
$(Q)$(MAKE_DIR) $(DESTDIR)$(LIBDIR)
$(Q)$(INSTALL_PROGRAM) $(LIBXXH) $(DESTDIR)$(LIBDIR)
$(Q)ln -sf $(LIBXXH) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT_MAJOR)
$(Q)ln -sf $(LIBXXH) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT)
install_libxxhash.includes:
$(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR) # includes
$(Q)$(INSTALL_DATA) xxhash.h $(DESTDIR)$(INCLUDEDIR)
$(Q)$(INSTALL_DATA) xxh3.h $(DESTDIR)$(INCLUDEDIR) # for compatibility, will be removed in v0.9.0
ifeq ($(LIBXXH_DISPATCH),1)
$(Q)$(INSTALL_DATA) xxh_x86dispatch.h $(DESTDIR)$(INCLUDEDIR)
endif
install_libxxhash.pc: libxxhash.pc
@echo Installing pkgconfig
$(Q)$(MAKE_DIR) $(DESTDIR)$(PKGCONFIGDIR)/
$(Q)$(INSTALL_DATA) libxxhash.pc $(DESTDIR)$(PKGCONFIGDIR)/
install_xxhsum: xxhsum
@echo Installing xxhsum
$(Q)$(MAKE_DIR) $(DESTDIR)$(BINDIR)/
$(Q)$(INSTALL_PROGRAM) xxhsum $(DESTDIR)$(BINDIR)/xxhsum
$(Q)ln -sf xxhsum $(DESTDIR)$(BINDIR)/xxh32sum
$(Q)ln -sf xxhsum $(DESTDIR)$(BINDIR)/xxh64sum
$(Q)ln -sf xxhsum $(DESTDIR)$(BINDIR)/xxh128sum
$(Q)ln -sf xxhsum $(DESTDIR)$(BINDIR)/xxh3sum
install_man:
@echo Installing man pages
$(Q)$(MAKE_DIR) $(DESTDIR)$(MANDIR)/
$(Q)$(INSTALL_DATA) $(MAN) $(DESTDIR)$(MANDIR)/xxhsum.1
$(Q)ln -sf xxhsum.1 $(DESTDIR)$(MANDIR)/xxh32sum.1
$(Q)ln -sf xxhsum.1 $(DESTDIR)$(MANDIR)/xxh64sum.1
$(Q)ln -sf xxhsum.1 $(DESTDIR)$(MANDIR)/xxh128sum.1
$(Q)ln -sf xxhsum.1 $(DESTDIR)$(MANDIR)/xxh3sum.1
.PHONY: install
install: lib pkgconfig xxhsum ## install libraries, CLI, links and man page
@echo Installing libxxhash
@$(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)
@$(INSTALL_DATA) libxxhash.a $(DESTDIR)$(LIBDIR)
@$(INSTALL_PROGRAM) $(LIBXXH) $(DESTDIR)$(LIBDIR)
@ln -sf $(LIBXXH) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT_MAJOR)
@ln -sf $(LIBXXH) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT)
@$(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR) # includes
@$(INSTALL_DATA) xxhash.h $(DESTDIR)$(INCLUDEDIR)
@$(INSTALL_DATA) xxh3.h $(DESTDIR)$(INCLUDEDIR)
@echo Installing pkgconfig
@$(INSTALL) -d -m 755 $(DESTDIR)$(PKGCONFIGDIR)/
@$(INSTALL_DATA) libxxhash.pc $(DESTDIR)$(PKGCONFIGDIR)/
@echo Installing xxhsum
@$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)/ $(DESTDIR)$(MANDIR)/
@$(INSTALL_PROGRAM) xxhsum $(DESTDIR)$(BINDIR)/xxhsum
@ln -sf xxhsum $(DESTDIR)$(BINDIR)/xxh32sum
@ln -sf xxhsum $(DESTDIR)$(BINDIR)/xxh64sum
@ln -sf xxhsum $(DESTDIR)$(BINDIR)/xxh128sum
@echo Installing man pages
@$(INSTALL_DATA) xxhsum.1 $(DESTDIR)$(MANDIR)/xxhsum.1
@ln -sf xxhsum.1 $(DESTDIR)$(MANDIR)/xxh32sum.1
@ln -sf xxhsum.1 $(DESTDIR)$(MANDIR)/xxh64sum.1
@ln -sf xxhsum.1 $(DESTDIR)$(MANDIR)/xxh128sum.1
## install libraries, CLI, links and man pages
install: install_libxxhash.a install_libxxhash install_libxxhash.includes install_libxxhash.pc install_xxhsum install_man
@echo xxhash installation completed
.PHONY: uninstall
uninstall: ## uninstall libraries, CLI, links and man page
@$(RM) $(DESTDIR)$(LIBDIR)/libxxhash.a
@$(RM) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT)
@$(RM) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT_MAJOR)
@$(RM) $(DESTDIR)$(LIBDIR)/$(LIBXXH)
@$(RM) $(DESTDIR)$(INCLUDEDIR)/xxhash.h
@$(RM) $(DESTDIR)$(PKGCONFIGDIR)/libxxhash.pc
@$(RM) $(DESTDIR)$(BINDIR)/xxh32sum
@$(RM) $(DESTDIR)$(BINDIR)/xxh64sum
@$(RM) $(DESTDIR)$(BINDIR)/xxh128sum
@$(RM) $(DESTDIR)$(BINDIR)/xxhsum
@$(RM) $(DESTDIR)$(MANDIR)/xxh32sum.1
@$(RM) $(DESTDIR)$(MANDIR)/xxh64sum.1
@$(RM) $(DESTDIR)$(MANDIR)/xxh128sum.1
@$(RM) $(DESTDIR)$(MANDIR)/xxhsum.1
$(Q)$(RM) $(DESTDIR)$(LIBDIR)/libxxhash.a
$(Q)$(RM) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT)
$(Q)$(RM) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT_MAJOR)
$(Q)$(RM) $(DESTDIR)$(LIBDIR)/$(LIBXXH)
$(Q)$(RM) $(DESTDIR)$(INCLUDEDIR)/xxhash.h
$(Q)$(RM) $(DESTDIR)$(INCLUDEDIR)/xxh3.h
$(Q)$(RM) $(DESTDIR)$(INCLUDEDIR)/xxh_x86dispatch.h
$(Q)$(RM) $(DESTDIR)$(PKGCONFIGDIR)/libxxhash.pc
$(Q)$(RM) $(DESTDIR)$(BINDIR)/xxh32sum
$(Q)$(RM) $(DESTDIR)$(BINDIR)/xxh64sum
$(Q)$(RM) $(DESTDIR)$(BINDIR)/xxh128sum
$(Q)$(RM) $(DESTDIR)$(BINDIR)/xxh3sum
$(Q)$(RM) $(DESTDIR)$(BINDIR)/xxhsum
$(Q)$(RM) $(DESTDIR)$(MANDIR)/xxh32sum.1
$(Q)$(RM) $(DESTDIR)$(MANDIR)/xxh64sum.1
$(Q)$(RM) $(DESTDIR)$(MANDIR)/xxh128sum.1
$(Q)$(RM) $(DESTDIR)$(MANDIR)/xxh3sum.1
$(Q)$(RM) $(DESTDIR)$(MANDIR)/xxhsum.1
@echo xxhsum successfully uninstalled
endif
+173 -107
View File
@@ -1,125 +1,178 @@
xxHash - Extremely fast hash algorithm
======================================
<!-- TODO: Update. -->
xxHash is an Extremely fast Hash algorithm, running at RAM speed limits.
It successfully completes the [SMHasher](https://code.google.com/p/smhasher/wiki/SMHasher) test suite
which evaluates collision, dispersion and randomness qualities of hash functions.
Code is highly portable, and hashes are identical on all platforms (little / big endian).
xxHash is an Extremely fast Hash algorithm, processing at RAM speed limits.
Code is highly portable, and produces hashes identical across all platforms (little / big endian).
The library includes the following algorithms :
- XXH32 : generates 32-bit hashes, using 32-bit arithmetic
- XXH64 : generates 64-bit hashes, using 64-bit arithmetic
- XXH3 (since `v0.8.0`): generates 64 or 128-bit hashes, using vectorized arithmetic.
The 128-bit variant is called XXH128.
All variants successfully complete the [SMHasher](https://code.google.com/p/smhasher/wiki/SMHasher) test suite
which evaluates the quality of hash functions (collision, dispersion and randomness).
Additional tests, which evaluate more thoroughly speed and collision properties of 64-bit hashes, [are also provided](https://github.com/Cyan4973/xxHash/tree/dev/tests).
|Branch |Status |
|------------|---------|
|master | [![Build Status](https://travis-ci.org/Cyan4973/xxHash.svg?branch=master)](https://travis-ci.org/Cyan4973/xxHash?branch=master) |
|dev | [![Build Status](https://travis-ci.org/Cyan4973/xxHash.svg?branch=dev)](https://travis-ci.org/Cyan4973/xxHash?branch=dev) |
|release | [![Build Status](https://github.com/Cyan4973/xxHash/actions/workflows/ci.yml/badge.svg?branch=release)](https://github.com/Cyan4973/xxHash/actions?query=branch%3Arelease+) |
|dev | [![Build Status](https://github.com/Cyan4973/xxHash/actions/workflows/ci.yml/badge.svg?branch=dev)](https://github.com/Cyan4973/xxHash/actions?query=branch%3Adev+) |
Benchmarks
-------------------------
The benchmark uses SMHasher speed test, compiled with Visual 2010 on a Windows Seven 32-bit box.
The reference system uses a Core 2 Duo @3GHz
The benchmarked reference system uses an Intel i7-9700K cpu, and runs Ubuntu x64 20.04.
The [open source benchmark program] is compiled with `clang` v10.0 using `-O3` flag.
| Hash Name | Width | Bandwidth (GB/s) | Small Data Velocity | Quality | Comment |
| --------- | ----- | ---------------- | ----- | --- | --- |
| __XXH3__ (SSE2) | 64 | 31.5 GB/s | 133.1 | 10
| __XXH128__ (SSE2) | 128 | 29.6 GB/s | 118.1 | 10
| _RAM sequential read_ | N/A | 28.0 GB/s | N/A | N/A | _for reference_
| City64 | 64 | 22.0 GB/s | 76.6 | 10
| T1ha2 | 64 | 22.0 GB/s | 99.0 | 9 | Slightly worse [collisions]
| City128 | 128 | 21.7 GB/s | 57.7 | 10
| __XXH64__ | 64 | 19.4 GB/s | 71.0 | 10
| SpookyHash | 64 | 19.3 GB/s | 53.2 | 10
| Mum | 64 | 18.0 GB/s | 67.0 | 9 | Slightly worse [collisions]
| __XXH32__ | 32 | 9.7 GB/s | 71.9 | 10
| City32 | 32 | 9.1 GB/s | 66.0 | 10
| Murmur3 | 32 | 3.9 GB/s | 56.1 | 10
| SipHash | 64 | 3.0 GB/s | 43.2 | 10
| FNV64 | 64 | 1.2 GB/s | 62.7 | 5 | Poor avalanche properties
| Blake2 | 256 | 1.1 GB/s | 5.1 | 10 | Cryptographic
| SHA1 | 160 | 0.8 GB/s | 5.6 | 10 | Cryptographic but broken
| MD5 | 128 | 0.6 GB/s | 7.8 | 10 | Cryptographic but broken
| Name | Speed | Quality | Author |
|---------------|--------------------|:-------:|-------------------|
| [xxHash] | 5.4 GB/s | 10 | Y.C. |
| MurmurHash 3a | 2.7 GB/s | 10 | Austin Appleby |
| SBox | 1.4 GB/s | 9 | Bret Mulvey |
| Lookup3 | 1.2 GB/s | 9 | Bob Jenkins |
| CityHash64 | 1.05 GB/s | 10 | Pike & Alakuijala |
| FNV | 0.55 GB/s | 5 | Fowler, Noll, Vo |
| CRC32 | 0.43 GB/s &dagger; | 9 | |
| MD5-32 | 0.33 GB/s | 10 | Ronald L.Rivest |
| SHA1-32 | 0.28 GB/s | 10 | |
[open source benchmark program]: https://github.com/Cyan4973/xxHash/tree/release/tests/bench
[collisions]: https://github.com/Cyan4973/xxHash/wiki/Collision-ratio-comparison#collision-study
[xxHash]: https://www.xxhash.com
note 1: Small data velocity is a _rough_ evaluation of algorithm's efficiency on small data. For more detailed analysis, please refer to next paragraph.
Note &dagger;: SMHasher's CRC32 implementation is known to be slow. Faster implementations exist.
note 2: some algorithms feature _faster than RAM_ speed. In which case, they can only reach their full speed potential when input is already in CPU cache (L3 or better). Otherwise, they max out on RAM speed limit.
Q.Score is a measure of quality of the hash function.
It depends on successfully passing SMHasher test set.
10 is a perfect score.
Algorithms with a score < 5 are not listed on this table.
### Small data
A more recent version, XXH64, has been created thanks to [Mathias Westerdahl](https://github.com/JCash),
which offers superior speed and dispersion for 64-bit systems.
Note however that 32-bit applications will still run faster using the 32-bit version.
Performance on large data is only one part of the picture.
Hashing is also very useful in constructions like hash tables and bloom filters.
In these use cases, it's frequent to hash a lot of small data (starting at a few bytes).
Algorithm's performance can be very different for such scenarios, since parts of the algorithm,
such as initialization or finalization, become fixed cost.
The impact of branch mis-prediction also becomes much more present.
SMHasher speed test, compiled using GCC 4.8.2, on Linux Mint 64-bit.
The reference system uses a Core i5-3340M @2.7GHz
| Version | Speed on 64-bit | Speed on 32-bit |
|------------|------------------|------------------|
| XXH64 | 13.8 GB/s | 1.9 GB/s |
| XXH32 | 6.8 GB/s | 6.0 GB/s |
This project also includes a command line utility, named `xxhsum`, offering similar features to `md5sum`,
thanks to [Takayuki Matsuoka](https://github.com/t-mat)'s contributions.
### License
The library files `xxhash.c` and `xxhash.h` are BSD licensed.
The utility `xxhsum` is GPL licensed.
### New hash algorithms
Starting with `v0.7.0`, the library includes a new algorithm named `XXH3`,
which is able to generate 64 and 128-bit hashes.
The new algorithm is much faster than its predecessors for both long and small inputs,
which can be observed in the following graphs:
![XXH3, bargraph](https://user-images.githubusercontent.com/750081/61976096-b3a35f00-af9f-11e9-8229-e0afc506c6ec.png)
XXH3 has been designed for excellent performance on both long and small inputs,
which can be observed in the following graph:
![XXH3, latency, random size](https://user-images.githubusercontent.com/750081/61976089-aedeab00-af9f-11e9-9239-e5375d6c080f.png)
To access these new prototypes, one needs to unlock their declaration, using the build macro `XXH_STATIC_LINKING_ONLY`.
For a more detailed analysis, please visit the wiki :
https://github.com/Cyan4973/xxHash/wiki/Performance-comparison#benchmarks-concentrating-on-small-data-
The algorithm is currently in development, meaning its return values might still change in future versions.
However, the API is stable, and can be used in production, typically for ephemeral
data (produced and consumed in same session).
Quality
-------------------------
`XXH3`'s return values will be finalized upon reaching `v0.8.0`.
Speed is not the only property that matters.
Produced hash values must respect excellent dispersion and randomness properties,
so that any sub-section of it can be used to maximally spread out a table or index,
as well as reduce the amount of collisions to the minimal theoretical level, following the [birthday paradox].
`xxHash` has been tested with Austin Appleby's excellent SMHasher test suite,
and passes all tests, ensuring reasonable quality levels.
It also passes extended tests from [newer forks of SMHasher], featuring additional scenarios and conditions.
Finally, xxHash provides its own [massive collision tester](https://github.com/Cyan4973/xxHash/tree/dev/tests/collisions),
able to generate and compare billions of hashes to test the limits of 64-bit hash algorithms.
On this front too, xxHash features good results, in line with the [birthday paradox].
A more detailed analysis is documented [in the wiki](https://github.com/Cyan4973/xxHash/wiki/Collision-ratio-comparison).
[birthday paradox]: https://en.wikipedia.org/wiki/Birthday_problem
[newer forks of SMHasher]: https://github.com/rurban/smhasher
### Build modifiers
The following macros can be set at compilation time to modify libxxhash's behavior. They are all disabled by default.
The following macros can be set at compilation time to modify `libxxhash`'s behavior. They are generally disabled by default.
- `XXH_INLINE_ALL`: Make all functions `inline`, with implementations being directly included within `xxhash.h`.
Inlining functions is beneficial for speed on small keys.
It's _extremely effective_ when key length is expressed as _a compile time constant_,
with performance improvements being observed in the +200% range .
- `XXH_INLINE_ALL`: Make all functions `inline`, implementation is directly included within `xxhash.h`.
Inlining functions is beneficial for speed, notably for small keys.
It's _extremely effective_ when key's length is expressed as _a compile time constant_,
with performance improvements observed in the +200% range .
See [this article](https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html) for details.
Note: there is no need to compile an `xxhash.o` object file in this case.
- `XXH_NO_INLINE_HINTS`: By default, xxHash uses tricks like `__attribute__((always_inline))` and `__forceinline` to try and improve performance at the cost of code size. Defining this to 1 will mark all internal functions as `static`, allowing the compiler to decide whether to inline a function or not. This is very useful when optimizing for the smallest binary size, and it is automatically defined when compiling with `-O0`, `-Os`, `-Oz`, or `-fno-inline` on GCC and Clang. This may also increase performance depending on the compiler and the architecture.
- `XXH_REROLL`: Reduces the size of the generated code by not unrolling some loops. Impact on performance may vary, depending on the platform and the algorithm.
- `XXH_ACCEPT_NULL_INPUT_POINTER`: if set to `1`, when input is a `NULL` pointer,
xxHash'd result is the same as a zero-length input
(instead of a dereference segfault).
Adds one branch at the beginning of the hash.
- `XXH_PRIVATE_API`: same outcome as `XXH_INLINE_ALL`. Still available for legacy support.
The name underlines that `XXH_*` symbol names will not be exported.
- `XXH_STATIC_LINKING_ONLY`: gives access to internal state declaration, required for static allocation.
Incompatible with dynamic linking, due to risks of ABI changes.
- `XXH_NAMESPACE`: Prefixes all symbols with the value of `XXH_NAMESPACE`.
This macro can only use compilable character set.
Useful to evade symbol naming collisions,
in case of multiple inclusions of xxHash's source code.
Client applications still use the regular function names,
as symbols are automatically translated through `xxhash.h`.
- `XXH_FORCE_ALIGN_CHECK`: Use a faster direct read path when input is aligned.
This option can result in dramatic performance improvement on architectures unable to load memory from unaligned addresses
when input to hash happens to be aligned on 32 or 64-bit boundaries.
It is (slightly) detrimental on platform with good unaligned memory access performance (same instruction for both aligned and unaligned accesses).
This option is automatically disabled on `x86`, `x64` and `aarch64`, and enabled on all other platforms.
- `XXH_FORCE_MEMORY_ACCESS`: The default method `0` uses a portable `memcpy()` notation.
Method `1` uses a gcc-specific `packed` attribute, which can provide better performance for some targets.
Method `2` forces unaligned reads, which is not standards compliant, but might sometimes be the only way to extract better read performance.
Method `3` uses a byteshift operation, which is best for old compilers which don't inline `memcpy()` or big-endian systems without a byteswap instruction
- `XXH_CPU_LITTLE_ENDIAN`: By default, endianess is determined at compile time.
It's possible to skip auto-detection and force format to little-endian, by setting this macro to 1.
Setting it to 0 forces big-endian.
- `XXH_PRIVATE_API`: same impact as `XXH_INLINE_ALL`.
Name underlines that XXH_* symbols will not be exported.
- `XXH_NAMESPACE`: Prefixes all symbols with the value of `XXH_NAMESPACE`.
Useful to evade symbol naming collisions,
in case of multiple inclusions of xxHash's source code.
Client applications can still use the regular function name,
as symbols are automatically translated through `xxhash.h`.
- `XXH_STATIC_LINKING_ONLY`: gives access to the state declaration for static allocation.
Incompatible with dynamic linking, due to risks of ABI changes.
- `XXH_NO_LONG_LONG`: removes support for XXH3 and XXH64 for targets without 64-bit support.
Method `2` forces unaligned reads, which is not standard compliant, but might sometimes be the only way to extract better read performance.
Method `3` uses a byteshift operation, which is best for old compilers which don't inline `memcpy()` or big-endian systems without a byteswap instruction.
- `XXH_CPU_LITTLE_ENDIAN`: By default, endianness is determined by a runtime test resolved at compile time.
If, for some reason, the compiler cannot simplify the runtime test, it can cost performance.
It's possible to skip auto-detection and simply state that the architecture is little-endian by setting this macro to 1.
Setting it to 0 states big-endian.
- `XXH_ENABLE_AUTOVECTORIZE`: Auto-vectorization may be triggered for XXH32 and XXH64, depending on cpu vector capabilities and compiler version.
Note: auto-vectorization tends to be triggered more easily with recent versions of `clang`.
For XXH32, SSE4.1 or equivalent (NEON) is enough, while XXH64 requires AVX512.
Unfortunately, auto-vectorization is generally detrimental to XXH performance.
For this reason, the xxhash source code tries to prevent auto-vectorization by default.
That being said, systems evolve, and this conclusion is not forthcoming.
For example, it has been reported that recent Zen4 cpus are more likely to improve performance with vectorization.
Therefore, should you prefer or want to test vectorized code, you can enable this flag:
it will remove the no-vectorization protection code, thus making it more likely for XXH32 and XXH64 to be auto-vectorized.
- `XXH32_ENDJMP`: Switch multi-branch finalization stage of XXH32 by a single jump.
This is generally undesirable for performance, especially when hashing inputs of random sizes.
But depending on exact architecture and compiler, a jump might provide slightly better performance on small inputs. Disabled by default.
- `XXH_IMPORT`: MSVC specific: should only be defined for dynamic linking, as it prevents linkage errors.
- `XXH_NO_STDLIB`: Disable invocation of `<stdlib.h>` functions, notably `malloc()` and `free()`.
`libxxhash`'s `XXH*_createState()` will always fail and return `NULL`.
But one-shot hashing (like `XXH32()`) or streaming using statically allocated states
still work as expected.
This build flag is useful for embedded environments without dynamic allocation.
- `XXH_DEBUGLEVEL` : When set to any value >= 1, enables `assert()` statements.
This (slightly) slows down execution, but may help finding bugs during debugging sessions.
#### Binary size control
- `XXH_NO_XXH3` : removes symbols related to `XXH3` (both 64 & 128 bits) from generated binary.
`XXH3` is by far the largest contributor to `libxxhash` size,
so it's useful to reduce binary size for applications which do not employ `XXH3`.
- `XXH_NO_LONG_LONG`: removes compilation of algorithms relying on 64-bit `long long` types
which include `XXH3` and `XXH64`.
Only `XXH32` will be compiled.
Useful for targets (architectures and compilers) without 64-bit support.
- `XXH_NO_STREAM`: Disables the streaming API, limiting the library to single shot variants only.
- `XXH_NO_INLINE_HINTS`: By default, xxHash uses `__attribute__((always_inline))` and `__forceinline` to improve performance at the cost of code size.
Defining this macro to 1 will mark all internal functions as `static`, allowing the compiler to decide whether to inline a function or not.
This is very useful when optimizing for smallest binary size,
and is automatically defined when compiling with `-O0`, `-Os`, `-Oz`, or `-fno-inline` on GCC and Clang.
It may also be required to successfully compile using `-Og`, depending on compiler version.
- `XXH_SIZE_OPT`: `0`: default, optimize for speed
`1`: default for `-Os` and `-Oz`: disables some speed hacks for size optimization
`2`: makes code as small as possible, performance may cry
#### Build modifiers specific for XXH3
- `XXH_VECTOR` : manually select a vector instruction set (default: auto-selected at compilation time). Available instruction sets are `XXH_SCALAR`, `XXH_SSE2`, `XXH_AVX2`, `XXH_AVX512`, `XXH_NEON` and `XXH_VSX`. Compiler may require additional flags to ensure proper support (for example, `gcc` on x86_64 requires `-mavx2` for `AVX2`, or `-mavx512f` for `AVX512`).
- `XXH_PREFETCH_DIST` : select prefetching distance. For close-to-metal adaptation to specific hardware platforms. XXH3 only.
- `XXH_NO_PREFETCH` : disable prefetching. Some platforms or situations may perform better without prefetching. XXH3 only.
#### Makefile variables
When compiling the Command Line Interface `xxhsum` using `make`, the following environment variables can also be set :
- `DISPATCH=1` : use `xxh_x86dispatch.c`, select at runtime between `scalar`, `sse2`, `avx2` or `avx512` instruction set. This option is only valid for `x86`/`x64` systems. It is enabled by default when target `x86`/`x64` is detected. It can be forcefully turned off using `DISPATCH=0`.
- `LIBXXH_DISPATCH=1` : same idea, implemented a runtime vector extension detector, but within `libxxhash`. This parameter is disabled by default. When enabled (only valid for `x86`/`x64` systems), new symbols published in `xxh_x86dispatch.h` become accessible. At the time of this writing, it's required to include `xxh_x86dispatch.h` in order to access the symbols with runtime vector extension detection.
- `XXH_1ST_SPEED_TARGET` : select an initial speed target, expressed in MB/s, for the first speed test in benchmark mode. Benchmark will adjust the target at subsequent iterations, but the first test is made "blindly" by targeting this speed. Currently conservatively set to 10 MB/s, to support very slow (emulated) platforms.
- `NODE_JS=1` : When compiling `xxhsum` for Node.js with Emscripten, this links the `NODERAWFS` library for unrestricted filesystem access and patches `isatty` to make the command line utility correctly detect the terminal. This does make the binary specific to Node.js.
### Building xxHash - Using vcpkg
@@ -133,10 +186,10 @@ You can download and install xxHash using the [vcpkg](https://github.com/Microso
The xxHash port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
### Example
Calling xxhash 64-bit variant from a C program:
The simplest example calls xxhash 64-bit variant as a one-shot function
generating a hash value from a single buffer, and invoked from a C/C++ program:
```C
#include "xxhash.h"
@@ -146,7 +199,8 @@ Calling xxhash 64-bit variant from a C program:
}
```
Using streaming variant is more involved, but makes it possible to provide data incrementally:
Streaming variant is more involved, but makes it possible to provide data incrementally:
```C
#include "stdlib.h" /* abort() */
#include "xxhash.h"
@@ -168,17 +222,17 @@ XXH64_hash_t calcul_hash_streaming(FileHandler fh)
/* Feed the state with input data, any size, any number of times */
(...)
while ( /* any condition */ ) {
size_t const length = get_more_data(buffer, bufferSize, fh);
while ( /* some data left */ ) {
size_t const length = get_more_data(buffer, bufferSize, fh);
if (XXH64_update(state, buffer, length) == XXH_ERROR) abort();
(...)
}
(...)
/* Get the hash */
/* Produce the final hash value */
XXH64_hash_t const hash = XXH64_digest(state);
/* State can be re-used; in this example, it is simply freed */
/* State could be re-used; but in this example, it is simply freed */
free(buffer);
XXH64_freeState(state);
@@ -187,19 +241,31 @@ XXH64_hash_t calcul_hash_streaming(FileHandler fh)
```
### License
The library files `xxhash.c` and `xxhash.h` are BSD licensed.
The utility `xxhsum` is GPL licensed.
### Other programming languages
Aside from the C reference version,
xxHash is also available in many different programming languages,
thanks to many great contributors.
They are [listed here](https://www.xxhash.com/#other-languages).
Beyond the C reference version,
xxHash is also available from many different programming languages,
thanks to great contributors.
They are [listed here](http://www.xxhash.com/#other-languages).
### Branch Policy
### Packaging status
> - The "master" branch is considered stable, at all times.
> - The "dev" branch is the one where all contributions must be merged
before being promoted to master.
> + If you plan to propose a patch, please commit into the "dev" branch,
or its own feature branch.
Direct commit to "master" are not permitted.
Many distributions bundle a package manager
which allows easy xxhash installation as both a `libxxhash` library
and `xxhsum` command line interface.
[![Packaging status](https://repology.org/badge/vertical-allrepos/xxhash.svg)](https://repology.org/project/xxhash/versions)
### Special Thanks
- Takayuki Matsuoka, aka @t-mat, for creating `xxhsum -c` and great support during early xxh releases
- Mathias Westerdahl, aka @JCash, for introducing the first version of `XXH64`
- Devin Hussey, aka @easyaspi314, for incredible low-level optimizations on `XXH3` and `XXH128`
+13
View File
@@ -0,0 +1,13 @@
# Security Policy
## Supported Versions
Security updates are applied only to the latest release.
## Reporting a Vulnerability
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
Please disclose it at [security advisory](https://github.com/Cyan4973/xxHash/security/advisories/new).
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure.
+18 -14
View File
@@ -13,10 +13,6 @@ environment:
- COMPILER: "visual"
ARCH: "x64"
TEST_XXHSUM: "true"
- COMPILER: "visual"
ARCH: "x64"
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TEST_XXHSUM: "true"
- COMPILER: "visual"
ARCH: "Win32"
TEST_XXHSUM: "true"
@@ -26,16 +22,24 @@ environment:
TEST_XXHSUM: "true"
- COMPILER: "visual"
ARCH: "ARM"
- COMPILER: "visual"
ARCH: "ARM64"
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
# note: ARM64 is not available with Visual Studio 14 2015, which is default for Appveyor
- COMPILER: "gcc"
PLATFORM: "mingw64"
- COMPILER: "gcc"
PLATFORM: "mingw32"
- COMPILER: "gcc"
PLATFORM: "clang"
# Below tests are now disabled due to redundancy.
# Their equivalent already runs correctly on Github Actions.
# - COMPILER: "visual"
# ARCH: "x64"
# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
# TEST_XXHSUM: "true"
# - COMPILER: "visual"
# ARCH: "ARM64"
# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
# # note: ARM64 is not available with Visual Studio 14 2015, which is default for Appveyor
# The following tests were also flacky on Appveyor, for various reasons.
# - COMPILER: "gcc"
# PLATFORM: "mingw64"
# - COMPILER: "gcc"
# PLATFORM: "mingw32"
# - COMPILER: "gcc"
# PLATFORM: "clang"
install:
- ECHO Installing %COMPILER% %PLATFORM% %ARCH%
+3
View File
@@ -0,0 +1,3 @@
{
"Cyan4973/xxHash": { }
}
View File
Whitespace-only changes.
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
+4
View File
@@ -0,0 +1,4 @@
This directory contains source code dedicated to the `xxhsum` command line utility,
which is a user program of `libxxhash`.
Note that, in contrast with the library `libxxhash`, the command line utility `xxhsum` ships with GPLv2 license.
+51
View File
@@ -0,0 +1,51 @@
/*
* xxhsum - Command line interface for xxhash algorithms
* Copyright (C) 2013-2024 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
int g_xsumarch_avoid_empty_unit = 0;
#if ((defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) && !defined(_M_ARM64EC)) || defined(__i386__) || defined(_M_IX86) || defined(_M_IX86_FP)
#if defined(XXHSUM_DISPATCH)
#include "../xxh_x86dispatch.h"
const char* XSUM_autox86(void)
{
int vecVersion = XXH_featureTest();
switch(vecVersion) {
case XXH_SCALAR:
return "x86 autoVec (scalar: no vector extension detected)";
case XXH_SSE2:
return "x86 autoVec (SSE2 detected)";
case XXH_AVX2:
return "x86 autoVec (AVX2 detected)";
case XXH_AVX512:
return "x86 autoVec (AVX512 detected)";
default:;
}
return " autoVec (error detecting vector extension)";
}
#endif /* XXHSUM_DISPATCH */
#endif /* x86 */
+172
View File
@@ -0,0 +1,172 @@
/*
* xxhsum - Command line interface for xxhash algorithms
* Copyright (C) 2013-2021 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
/*
* Checks for predefined macros by the compiler to try and get both the arch
* and the compiler version.
*/
#ifndef XSUM_ARCH_H
#define XSUM_ARCH_H
#include "xsum_config.h"
#define XSUM_LIB_VERSION XXH_VERSION_MAJOR.XXH_VERSION_MINOR.XXH_VERSION_RELEASE
#define XSUM_QUOTE(str) #str
#define XSUM_EXPAND_AND_QUOTE(str) XSUM_QUOTE(str)
#define XSUM_PROGRAM_VERSION XSUM_EXPAND_AND_QUOTE(XSUM_LIB_VERSION)
/* Show compiler versions in WELCOME_MESSAGE. XSUM_CC_VERSION_FMT will return the printf specifiers,
* and VERSION will contain the comma separated list of arguments to the XSUM_CC_VERSION_FMT string. */
#if defined(__clang_version__)
/* Clang does its own thing. */
# ifdef __apple_build_version__
# define XSUM_CC_VERSION_FMT "Apple Clang %s"
# else
# define XSUM_CC_VERSION_FMT "Clang %s"
# endif
# define XSUM_CC_VERSION __clang_version__
#elif defined(__VERSION__)
/* GCC and ICC */
# define XSUM_CC_VERSION_FMT "%s"
# ifdef __INTEL_COMPILER /* icc adds its prefix */
# define XSUM_CC_VERSION __VERSION__
# else /* assume GCC */
# define XSUM_CC_VERSION "GCC " __VERSION__
# endif
#elif defined(_MSC_FULL_VER) && defined(_MSC_BUILD)
/*
* MSVC
* "For example, if the version number of the Visual C++ compiler is
* 15.00.20706.01, the _MSC_FULL_VER macro evaluates to 150020706."
*
* https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017
*/
# define XSUM_CC_VERSION_FMT "MSVC %02i.%02i.%05i.%02i"
# define XSUM_CC_VERSION _MSC_FULL_VER / 10000000 % 100, _MSC_FULL_VER / 100000 % 100, _MSC_FULL_VER % 100000, _MSC_BUILD
#elif defined(_MSC_VER) /* old MSVC */
# define XSUM_CC_VERSION_FMT "MSVC %02i.%02i"
# define XSUM_CC_VERSION _MSC_VER / 100, _MSC_VER % 100
#elif defined(__TINYC__)
/* tcc stores its version in the __TINYC__ macro. */
# define XSUM_CC_VERSION_FMT "tcc %i.%i.%i"
# define XSUM_CC_VERSION __TINYC__ / 10000 % 100, __TINYC__ / 100 % 100, __TINYC__ % 100
#else
# define XSUM_CC_VERSION_FMT "%s"
# define XSUM_CC_VERSION "unknown compiler"
#endif
/* makes the next part easier */
#if (defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) && !defined(_M_ARM64EC)
# define XSUM_ARCH_X64 1
# define XSUM_ARCH_X86 "x86_64"
#elif defined(__i386__) || defined(_M_IX86) || defined(_M_IX86_FP)
# define XSUM_ARCH_X86 "i386"
#endif
/* Try to detect the architecture. */
#if defined(XSUM_ARCH_X86)
# if defined(XXHSUM_DISPATCH)
const char* XSUM_autox86(void);
# define XSUM_ARCH XSUM_autox86()
# elif defined(__AVX512F__)
# define XSUM_ARCH XSUM_ARCH_X86 " + AVX512"
# elif defined(__AVX2__)
# define XSUM_ARCH XSUM_ARCH_X86 " + AVX2"
# elif defined(__AVX__)
# define XSUM_ARCH XSUM_ARCH_X86 " + AVX"
# elif defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) \
|| defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP == 2)
# define XSUM_ARCH XSUM_ARCH_X86 " + SSE2"
# else
# define XSUM_ARCH XSUM_ARCH_X86
# endif
#elif defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
# if defined(__ARM_FEATURE_SVE)
# define XSUM_ARCH "aarch64 + SVE"
# else
# define XSUM_ARCH "aarch64 + NEON"
# endif
#elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__) || defined(_M_ARM)
/* ARM has a lot of different features that can change xxHash significantly. */
# ifdef __ARM_ARCH
# define XSUM_ARCH_ARM_VER XSUM_EXPAND_AND_QUOTE(__ARM_ARCH)
# else
# define XSUM_ARCH_ARM_VER XSUM_EXPAND_AND_QUOTE(_M_ARM)
# endif
# if defined(_M_ARM) /* windows arm is always thumb-2 */ \
|| defined(__thumb2__) || (defined(__thumb__) && (__thumb__ == 2 || __ARM_ARCH >= 7))
# define XSUM_ARCH_THUMB " Thumb-2"
# elif defined(__thumb__)
# define XSUM_ARCH_THUMB " Thumb-1"
# else
# define XSUM_ARCH_THUMB ""
# endif
/* ARMv7 has unaligned by default */
# if defined(__ARM_FEATURE_UNALIGNED) || __ARM_ARCH >= 7 || defined(_M_ARM)
# define XSUM_ARCH_UNALIGNED " + unaligned"
# else
# define XSUM_ARCH_UNALIGNED ""
# endif
# if defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(_M_ARM)
# define XSUM_ARCH_NEON " + NEON"
# else
# define XSUM_ARCH_NEON ""
# endif
# define XSUM_ARCH "ARMv" XSUM_ARCH_ARM_VER XSUM_ARCH_THUMB XSUM_ARCH_NEON XSUM_ARCH_UNALIGNED
#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)
# if defined(__GNUC__) && defined(__POWER9_VECTOR__)
# define XSUM_ARCH "ppc64 + POWER9 vector"
# elif defined(__GNUC__) && defined(__POWER8_VECTOR__)
# define XSUM_ARCH "ppc64 + POWER8 vector"
# else
# define XSUM_ARCH "ppc64"
# endif
#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__)
# define XSUM_ARCH "ppc"
#elif defined(__AVR)
# define XSUM_ARCH "AVR"
#elif defined(__mips64)
# define XSUM_ARCH "mips64"
#elif defined(__mips)
# define XSUM_ARCH "mips"
#elif defined(__s390x__)
# define XSUM_ARCH "s390x"
#elif defined(__s390__)
# define XSUM_ARCH "s390"
#elif defined(__wasm__) || defined(__asmjs__) || defined(__EMSCRIPTEN__)
# if defined(__wasm_simd128__)
# define XSUM_ARCH "wasm/asmjs + simd128"
# else
# define XSUM_ARCH "wasm/asmjs"
# endif
#elif defined(__loongarch_lp64)
# define XSUM_ARCH "loongarch"
#else
# define XSUM_ARCH "unknown"
#endif
#endif /* XSUM_ARCH_H */
+452
View File
@@ -0,0 +1,452 @@
/*
* xsum_bench - Benchmark functions for xxhsum
* Copyright (C) 2013-2021 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
#include "xsum_output.h" /* XSUM_logLevel */
#include "xsum_bench.h"
#include "xsum_sanity_check.h" /* XSUM_fillTestBuffer */
#include "xsum_os_specific.h" /* XSUM_getFileSize */
#ifndef XXH_STATIC_LINKING_ONLY
# define XXH_STATIC_LINKING_ONLY
#endif
#include "../xxhash.h"
#ifdef XXHSUM_DISPATCH
# include "../xxh_x86dispatch.h" /* activate _dispatch() redirectors */
#endif
#include <stdlib.h> /* malloc, free */
#include <assert.h>
#include <string.h> /* strlen, memcpy */
#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
#include <errno.h> /* errno */
#define TIMELOOP_S 1
#define TIMELOOP (TIMELOOP_S * CLOCKS_PER_SEC) /* target timing per iteration */
#define TIMELOOP_MIN (TIMELOOP / 2) /* minimum timing to validate a result */
/* Each benchmark iteration attempts to match TIMELOOP (1 second).
* The nb of loops is adjusted at each iteration to reach that target.
* However, initially, there is no information, so 1st iteration blindly targets an arbitrary speed.
* If it's too small, it will be adjusted, and a new attempt will be made.
* But if it's too large, the first iteration can be very long,
* before being fixed at second attempt.
* So prefer starting with small speed targets.
* XXH_1ST_SPEED_TARGET is defined in MB/s */
#ifndef XXH_1ST_SPEED_TARGET
# define XXH_1ST_SPEED_TARGET 10
#endif
#define MAX_MEM (2 GB - 64 MB)
static clock_t XSUM_clockSpan( clock_t start )
{
return clock() - start; /* works even if overflow; Typical max span ~ 30 mn */
}
static size_t XSUM_findMaxMem(XSUM_U64 requiredMem)
{
size_t const step = 64 MB;
void* testmem = NULL;
requiredMem = (((requiredMem >> 26) + 1) << 26);
requiredMem += 2*step;
if (requiredMem > MAX_MEM) requiredMem = MAX_MEM;
while (!testmem) {
if (requiredMem > step) requiredMem -= step;
else requiredMem >>= 1;
testmem = malloc ((size_t)requiredMem);
}
free (testmem);
/* keep some space available */
if (requiredMem > step) requiredMem -= step;
else requiredMem >>= 1;
return (size_t)requiredMem;
}
/*
* A secret buffer used for benchmarking XXH3's withSecret variants.
*
* In order for the bench to be realistic, the secret buffer would need to be
* pre-generated.
*
* Adding a pointer to the parameter list would be messy.
*/
static XSUM_U8 g_benchSecretBuf[XXH3_SECRET_SIZE_MIN];
/*
* Wrappers for the benchmark.
*
* If you would like to add other hashes to the bench, create a wrapper and add
* it to the g_hashesToBench table. It will automatically be added.
*/
typedef XSUM_U32 (*hashFunction)(const void* buffer, size_t bufferSize, XSUM_U32 seed);
static XSUM_U32 localXXH32(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
return XXH32(buffer, bufferSize, seed);
}
static XSUM_U32 localXXH32_stream(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
XXH32_state_t state;
(void)seed;
XXH32_reset(&state, seed);
XXH32_update(&state, buffer, bufferSize);
return (XSUM_U32)XXH32_digest(&state);
}
static XSUM_U32 localXXH64(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
return (XSUM_U32)XXH64(buffer, bufferSize, seed);
}
static XSUM_U32 localXXH64_stream(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
XXH64_state_t state;
(void)seed;
XXH64_reset(&state, seed);
XXH64_update(&state, buffer, bufferSize);
return (XSUM_U32)XXH64_digest(&state);
}
static XSUM_U32 localXXH3_64b(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
(void)seed;
return (XSUM_U32)XXH3_64bits(buffer, bufferSize);
}
static XSUM_U32 localXXH3_64b_seeded(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
return (XSUM_U32)XXH3_64bits_withSeed(buffer, bufferSize, seed);
}
static XSUM_U32 localXXH3_64b_secret(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
(void)seed;
return (XSUM_U32)XXH3_64bits_withSecret(buffer, bufferSize, g_benchSecretBuf, sizeof(g_benchSecretBuf));
}
static XSUM_U32 localXXH3_128b(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
(void)seed;
return (XSUM_U32)(XXH3_128bits(buffer, bufferSize).low64);
}
static XSUM_U32 localXXH3_128b_seeded(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
return (XSUM_U32)(XXH3_128bits_withSeed(buffer, bufferSize, seed).low64);
}
static XSUM_U32 localXXH3_128b_secret(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
(void)seed;
return (XSUM_U32)(XXH3_128bits_withSecret(buffer, bufferSize, g_benchSecretBuf, sizeof(g_benchSecretBuf)).low64);
}
static XSUM_U32 localXXH3_stream(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
XXH3_state_t state;
(void)seed;
XXH3_64bits_reset(&state);
XXH3_64bits_update(&state, buffer, bufferSize);
return (XSUM_U32)XXH3_64bits_digest(&state);
}
static XSUM_U32 localXXH3_stream_seeded(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
XXH3_state_t state;
XXH3_INITSTATE(&state);
XXH3_64bits_reset_withSeed(&state, (XXH64_hash_t)seed);
XXH3_64bits_update(&state, buffer, bufferSize);
return (XSUM_U32)XXH3_64bits_digest(&state);
}
static XSUM_U32 localXXH128_stream(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
XXH3_state_t state;
(void)seed;
XXH3_128bits_reset(&state);
XXH3_128bits_update(&state, buffer, bufferSize);
return (XSUM_U32)(XXH3_128bits_digest(&state).low64);
}
static XSUM_U32 localXXH128_stream_seeded(const void* buffer, size_t bufferSize, XSUM_U32 seed)
{
XXH3_state_t state;
XXH3_INITSTATE(&state);
XXH3_128bits_reset_withSeed(&state, (XXH64_hash_t)seed);
XXH3_128bits_update(&state, buffer, bufferSize);
return (XSUM_U32)(XXH3_128bits_digest(&state).low64);
}
typedef struct {
const char* name;
hashFunction func;
} hashInfo;
static const hashInfo g_hashesToBench[] = {
{ "XXH32", &localXXH32 },
{ "XXH64", &localXXH64 },
{ "XXH3_64b", &localXXH3_64b },
{ "XXH3_64b w/seed", &localXXH3_64b_seeded },
{ "XXH3_64b w/secret", &localXXH3_64b_secret },
{ "XXH128", &localXXH3_128b },
{ "XXH128 w/seed", &localXXH3_128b_seeded },
{ "XXH128 w/secret", &localXXH3_128b_secret },
{ "XXH32_stream", &localXXH32_stream },
{ "XXH64_stream", &localXXH64_stream },
{ "XXH3_stream", &localXXH3_stream },
{ "XXH3_stream w/seed",&localXXH3_stream_seeded },
{ "XXH128_stream", &localXXH128_stream },
{ "XXH128_stream w/seed",&localXXH128_stream_seeded },
};
#define NB_HASHFUNC (sizeof(g_hashesToBench) / sizeof(*g_hashesToBench))
#define NB_TESTFUNC (1 + 2 * NB_HASHFUNC)
int const g_nbTestFunctions = NB_TESTFUNC;
char g_testIDs[NB_TESTFUNC] = { 0 };
const char k_testIDs_default[NB_TESTFUNC] = { 0,
1 /*XXH32*/, 0,
1 /*XXH64*/, 0,
1 /*XXH3*/, 0, 0, 0, 0, 0,
1 /*XXH128*/ };
int g_nbIterations = NBLOOPS_DEFAULT;
#define HASHNAME_MAX 29
static void XSUM_benchHash(hashFunction h, const char* hName, int testID,
const void* buffer, size_t bufferSize)
{
XSUM_U32 nbh_perIteration = (XSUM_U32)((XXH_1ST_SPEED_TARGET MB) / (bufferSize+1)) + 1;
int iterationNb, nbIterations = g_nbIterations + !g_nbIterations /* min 1 */;
double fastestH = 100000000.;
assert(HASHNAME_MAX > 2);
XSUM_logVerbose(2, "\r%80s\r", ""); /* Clean display line */
for (iterationNb = 1; iterationNb <= nbIterations; iterationNb++) {
XSUM_U32 r=0;
clock_t cStart;
XSUM_logVerbose(2, "%2i-%-*.*s : %10u ->\r",
iterationNb,
HASHNAME_MAX, HASHNAME_MAX, hName,
(unsigned)bufferSize);
cStart = clock();
while (clock() == cStart); /* starts clock() at its exact beginning */
cStart = clock();
{ XSUM_U32 u;
for (u=0; u<nbh_perIteration; u++)
r += h(buffer, bufferSize, u);
}
if (r==0) XSUM_logVerbose(3,".\r"); /* do something with r to defeat compiler "optimizing" hash away */
{ clock_t const nbTicks = XSUM_clockSpan(cStart);
double const ticksPerHash = ((double)nbTicks / TIMELOOP) / nbh_perIteration;
/*
* clock() is the only decent portable timer, but it isn't very
* precise.
*
* Sometimes, this lack of precision is enough that the benchmark
* finishes before there are enough ticks to get a meaningful result.
*
* For example, on a Core 2 Duo (without any sort of Turbo Boost),
* the imprecise timer caused peculiar results like so:
*
* XXH3_64b 4800.0 MB/s // conveniently even
* XXH3_64b unaligned 4800.0 MB/s
* XXH3_64b seeded 9600.0 MB/s // magical 2x speedup?!
* XXH3_64b seeded unaligned 4800.0 MB/s
*
* If we sense a suspiciously low number of ticks, we increase the
* iterations until we can get something meaningful.
*/
if (nbTicks < TIMELOOP_MIN) {
/* Not enough time spent in benchmarking, risk of rounding bias */
if (nbTicks == 0) { /* faster than resolution timer */
nbh_perIteration *= 100;
} else {
/*
* update nbh_perIteration so that the next round lasts
* approximately 1 second.
*/
double nbh_perSecond = (1 / ticksPerHash) + 1;
if (nbh_perSecond > (double)(4000U<<20)) nbh_perSecond = (double)(4000U<<20); /* avoid overflow */
nbh_perIteration = (XSUM_U32)nbh_perSecond;
}
/* g_nbIterations==0 => quick evaluation, no claim of accuracy */
if (g_nbIterations>0) {
iterationNb--; /* new round for a more accurate speed evaluation */
continue;
}
}
if (ticksPerHash < fastestH) fastestH = ticksPerHash;
if (fastestH>0.) { /* avoid div by zero */
XSUM_logVerbose(2, "%2i-%-*.*s : %10u -> %8.0f it/s (%7.1f MB/s) \r",
iterationNb,
HASHNAME_MAX, HASHNAME_MAX, hName,
(unsigned)bufferSize,
(double)1 / fastestH,
((double)bufferSize / (1 MB)) / fastestH);
} }
{ double nbh_perSecond = (1 / fastestH) + 1;
if (nbh_perSecond > (double)(4000U<<20)) nbh_perSecond = (double)(4000U<<20); /* avoid overflow */
nbh_perIteration = (XSUM_U32)nbh_perSecond;
}
}
XSUM_logVerbose(1, "%2i#%-*.*s : %10u -> %8.0f it/s (%7.1f MB/s) \n",
testID,
HASHNAME_MAX, HASHNAME_MAX, hName,
(unsigned)bufferSize,
(double)1 / fastestH,
((double)bufferSize / (1 MB)) / fastestH);
if (XSUM_logLevel<1)
XSUM_logVerbose(0, "%u, ", (unsigned)((double)1 / fastestH));
}
/*
* Allocates a string containing s1 and s2 concatenated. Acts like strdup.
* The result must be freed.
*/
static char* XSUM_strcatDup(const char* s1, const char* s2)
{
assert(s1 != NULL);
assert(s2 != NULL);
{ size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
char* buf = (char*)malloc(len1 + len2 + 1);
if (buf != NULL) {
/* strcpy(buf, s1) */
memcpy(buf, s1, len1);
/* strcat(buf, s2) */
memcpy(buf + len1, s2, len2 + 1);
}
return buf;
}
}
/*!
* XSUM_benchMem():
* Benchmark provided content up to twice per function:
* - once at provided aligned memory address (%16)
* - second time at unaligned memory address (+3)
* Enabled functions and modes are provided via @g_hashesToBench global variable.
* @buffer: Must be 16-byte aligned.
* The allocated size of underlying @buffer must be >= (@bufferSize+3).
* This function also fills @g_benchSecretBuf, to bench XXH3's _withSecret() variants.
*/
static void XSUM_benchMem(const void* buffer, size_t bufferSize)
{
assert((((size_t)buffer) & 15) == 0); /* ensure alignment */
XSUM_fillTestBuffer(g_benchSecretBuf, sizeof(g_benchSecretBuf));
{ int i;
for (i = 1; i < (int)NB_TESTFUNC; i++) {
int const hashFuncID = (i-1) / 2;
assert(g_hashesToBench[hashFuncID].name != NULL);
if (g_testIDs[i] == 0) continue;
/* aligned */
if ((i % 2) == 1) {
XSUM_benchHash(g_hashesToBench[hashFuncID].func, g_hashesToBench[hashFuncID].name, i, buffer, bufferSize);
}
/* unaligned */
if ((i % 2) == 0) {
/* Append "unaligned". */
char* const hashNameBuf = XSUM_strcatDup(g_hashesToBench[hashFuncID].name, " unaligned");
assert(hashNameBuf != NULL);
XSUM_benchHash(g_hashesToBench[hashFuncID].func, hashNameBuf, i, ((const char*)buffer)+3, bufferSize);
free(hashNameBuf);
}
} }
}
static size_t XSUM_selectBenchedSize(const char* fileName)
{
XSUM_U64 const inFileSize = XSUM_getFileSize(fileName);
size_t benchedSize = (size_t) XSUM_findMaxMem(inFileSize);
if ((XSUM_U64)benchedSize > inFileSize) benchedSize = (size_t)inFileSize;
if (benchedSize < inFileSize) {
XSUM_log("Not enough memory for '%s' full size; testing %i MB only...\n", fileName, (int)(benchedSize>>20));
}
return benchedSize;
}
int XSUM_benchFiles(const char* fileNamesTable[], int nbFiles)
{
int fileIdx;
for (fileIdx=0; fileIdx<nbFiles; fileIdx++) {
const char* const inFileName = fileNamesTable[fileIdx];
assert(inFileName != NULL);
{ FILE* const inFile = XSUM_fopen( inFileName, "rb" );
size_t const benchedSize = XSUM_selectBenchedSize(inFileName);
char* const buffer = (char*)calloc(benchedSize+16+3, 1);
void* const alignedBuffer = (buffer+15) - (((size_t)(buffer+15)) & 0xF); /* align on next 16 bytes */
/* Checks */
if (inFile==NULL){
XSUM_log("Error: Could not open '%s': %s.\n", inFileName, strerror(errno));
free(buffer);
exit(11);
}
if(!buffer) {
XSUM_log("\nError: Out of memory.\n");
fclose(inFile);
exit(12);
}
/* Fill input buffer */
{ size_t const readSize = fread(alignedBuffer, 1, benchedSize, inFile);
fclose(inFile);
if(readSize != benchedSize) {
XSUM_log("\nError: Could not read '%s': %s.\n", inFileName, strerror(errno));
free(buffer);
exit(13);
} }
/* bench */
XSUM_benchMem(alignedBuffer, benchedSize);
free(buffer);
} }
return 0;
}
int XSUM_benchInternal(size_t keySize)
{
void* const buffer = calloc(keySize+16+3, 1);
if (buffer == NULL) {
XSUM_log("\nError: Out of memory.\n");
exit(12);
}
{ const void* const alignedBuffer = ((char*)buffer+15) - (((size_t)((char*)buffer+15)) & 0xF); /* align on next 16 bytes */
/* bench */
XSUM_logVerbose(1, "Sample of ");
if (keySize > 10 KB) {
XSUM_logVerbose(1, "%u KB", (unsigned)(keySize >> 10));
} else {
XSUM_logVerbose(1, "%u bytes", (unsigned)keySize);
}
XSUM_logVerbose(1, "... \n");
XSUM_benchMem(alignedBuffer, keySize);
free(buffer);
}
return 0;
}
+51
View File
@@ -0,0 +1,51 @@
/*
* xsum_bench - Benchmark functions for xxhsum
* Copyright (C) 2013-2021 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
#ifndef XSUM_BENCH_H
#define XSUM_BENCH_H
#include <stddef.h> /* size_t */
#define NBLOOPS_DEFAULT 3 /* Default number of benchmark iterations */
extern int const g_nbTestFunctions;
extern char g_testIDs[]; /* size : g_nbTestFunctions */
extern const char k_testIDs_default[];
extern int g_nbIterations;
int XSUM_benchInternal(size_t keySize);
int XSUM_benchFiles(const char* fileNamesTable[], int nbFiles);
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* XSUM_BENCH_H */
+214
View File
@@ -0,0 +1,214 @@
/*
* xxhsum - Command line interface for xxhash algorithms
* Copyright (C) 2013-2021 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
/*
* This contains various configuration parameters and feature detection for
* xxhsum.
*
* Similar to config.h in Autotools, this should be the first header included.
*/
#ifndef XSUM_CONFIG_H
#define XSUM_CONFIG_H
/* ************************************
* Compiler Options
**************************************/
/*
* Disable Visual C's warnings when using the "insecure" CRT functions instead
* of the "secure" _s functions.
*
* These functions are not portable, and aren't necessary if you are using the
* original functions properly.
*/
#if defined(_MSC_VER) || defined(_WIN32)
# ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
# endif
#endif
/* Under Linux at least, pull in the *64 commands */
#ifndef _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE
#endif
#ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
#endif
/*
* So we can use __attribute__((__format__))
*/
#ifdef __GNUC__
# define XSUM_ATTRIBUTE(x) __attribute__(x)
#else
# define XSUM_ATTRIBUTE(x)
#endif
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) /* UNIX-like OS */ \
|| defined(__midipix__) || defined(__VMS))
# if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1-2001 (SUSv3) conformant */ \
|| defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) /* BSD distros */
# define XSUM_PLATFORM_POSIX_VERSION 200112L
# else
# if defined(__linux__) || defined(__linux)
# ifndef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 200112L /* use feature test macro */
# endif
# endif
# include <unistd.h> /* declares _POSIX_VERSION */
# if defined(_POSIX_VERSION) /* POSIX compliant */
# define XSUM_PLATFORM_POSIX_VERSION _POSIX_VERSION
# else
# define XSUM_PLATFORM_POSIX_VERSION 0
# endif
# endif
#endif
#if !defined(XSUM_PLATFORM_POSIX_VERSION)
# define XSUM_PLATFORM_POSIX_VERSION -1
#endif
#if !defined(S_ISREG)
# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
#endif
/* ************************************
* Windows helpers
**************************************/
/*
* Whether to use the Windows UTF-16 APIs instead of the portable libc 8-bit
* ("ANSI") APIs.
*
* Windows is not UTF-8 clean by default, and the only way to access every file
* on the OS is to use UTF-16.
*
* Do note that xxhsum uses UTF-8 internally and only uses UTF-16 for command
* line arguments, console I/O, and opening files.
*
* Additionally, this guarantees all piped output is UTF-8.
*/
#if defined(XSUM_WIN32_USE_WCHAR) && !defined(_WIN32)
/* We use Windows APIs, only use this on Windows. */
# undef XSUM_WIN32_USE_WCHAR
#endif
#ifndef XSUM_WIN32_USE_WCHAR
# if defined(_WIN32)
# include <wchar.h>
# if WCHAR_MAX == 0xFFFFU /* UTF-16 wchar_t */
# define XSUM_WIN32_USE_WCHAR 1
# else
# define XSUM_WIN32_USE_WCHAR 0
# endif
# else
# define XSUM_WIN32_USE_WCHAR 0
# endif
#endif
#if !XSUM_WIN32_USE_WCHAR
/*
* It doesn't make sense to have one without the other.
* Due to XSUM_WIN32_USE_WCHAR being undef'd, this also handles
* non-WIN32 platforms.
*/
# undef XSUM_WIN32_USE_WMAIN
# define XSUM_WIN32_USE_WMAIN 0
#else
/*
* Whether to use wmain() or main().
*
* wmain() is preferred because we don't have to mess with internal hidden
* APIs.
*
* It always works on MSVC, but in MinGW, it only works on MinGW-w64 with the
* -municode flag.
*
* Therefore we have to use main() -- there is no better option.
*/
# ifndef XSUM_WIN32_USE_WMAIN
# if defined(_UNICODE) || defined(UNICODE) /* MinGW -municode */ \
|| defined(_MSC_VER) /* MSVC */
# define XSUM_WIN32_USE_WMAIN 1
# else
# define XSUM_WIN32_USE_WMAIN 0
# endif
# endif
/*
* It is always good practice to define these to prevent accidental use of the
* ANSI APIs, even if the program primarily uses UTF-8.
*/
# ifndef _UNICODE
# define _UNICODE
# endif
# ifndef UNICODE
# define UNICODE
# endif
#endif /* XSUM_WIN32_USE_WCHAR */
#ifndef XSUM_API
# ifdef XXH_INLINE_ALL
# define XSUM_API static
# else
# define XSUM_API
# endif
#endif
#ifndef XSUM_NO_TESTS
# define XSUM_NO_TESTS 0
#endif
/* ***************************
* Basic types
* ***************************/
#if defined(__cplusplus) /* C++ */ \
|| (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) /* C99 */
# include <stdint.h>
typedef uint8_t XSUM_U8;
typedef uint32_t XSUM_U32;
typedef uint64_t XSUM_U64;
# else
# include <limits.h>
typedef unsigned char XSUM_U8;
# if UINT_MAX == 0xFFFFFFFFUL
typedef unsigned int XSUM_U32;
# else
typedef unsigned long XSUM_U32;
# endif
typedef unsigned long long XSUM_U64;
#endif /* not C++/C99 */
/* ***************************
* Common constants
* ***************************/
#define KB *( 1<<10)
#define MB *( 1<<20)
#define GB *(1U<<30)
#endif /* XSUM_CONFIG_H */
+523
View File
@@ -0,0 +1,523 @@
/*
* xxhsum - Command line interface for xxhash algorithms
* Copyright (C) 2013-2021 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
#include "xsum_os_specific.h" /* XSUM_API */
#include <sys/stat.h> /* stat() / _stat64() */
/*
* This file contains all of the ugly boilerplate to make xxhsum work across
* platforms.
*/
#if defined(_MSC_VER) || XSUM_WIN32_USE_WCHAR
typedef struct __stat64 XSUM_stat_t;
# if defined(_MSC_VER)
typedef int mode_t;
# endif
#else
typedef struct stat XSUM_stat_t;
#endif
#if defined(__EMSCRIPTEN__) && defined(XSUM_NODE_JS)
# include <unistd.h> /* isatty */
# include <emscripten.h> /* EM_ASM_INT */
/* The Emscripten SDK does not properly detect when the standard streams
* are piped to node.js, and there does not seem to be any way to tell in
* plain C. To work around it, inline JavaScript is used to call Node's
* isatty() function. */
static int XSUM_IS_CONSOLE(FILE* stdStream)
{
/* https://github.com/iliakan/detect-node */
int is_node = EM_ASM_INT((
return (Object.prototype.toString.call(
typeof process !== 'undefined' ? process : 0
) == '[object process]') | 0
));
if (is_node) {
return EM_ASM_INT(
return require('node:tty').isatty($0),
fileno(stdStream)
);
} else {
return isatty(fileno(stdStream));
}
}
#elif defined(__EMSCRIPTEN__) || (defined(__linux__) && (XSUM_PLATFORM_POSIX_VERSION >= 1)) \
|| (XSUM_PLATFORM_POSIX_VERSION >= 200112L) \
|| defined(__DJGPP__) \
|| defined(__MSYS__) \
|| defined(__HAIKU__)
# ifdef __OpenBSD__
# include <errno.h> /* errno */
# include <string.h> /* strerror */
# include "xsum_output.h" /* XSUM_log */
# endif
# include <unistd.h> /* isatty */
# define XSUM_IS_CONSOLE(stdStream) isatty(fileno(stdStream))
#elif defined(MSDOS) || defined(OS2)
# include <io.h> /* _isatty */
# define XSUM_IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))
#elif defined(_WIN32)
# include <io.h> /* _isatty */
# include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */
# include <stdio.h> /* FILE */
static __inline int XSUM_IS_CONSOLE(FILE* stdStream)
{
DWORD dummy;
return _isatty(_fileno(stdStream)) && GetConsoleMode((HANDLE)_get_osfhandle(_fileno(stdStream)), &dummy);
}
#else
# define XSUM_IS_CONSOLE(stdStream) 0
#endif
#if defined(MSDOS) || defined(OS2) || defined(_WIN32)
# include <fcntl.h> /* _O_BINARY */
# include <io.h> /* _setmode, _fileno, _get_osfhandle */
# if !defined(__DJGPP__)
# include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */
# include <winioctl.h> /* FSCTL_SET_SPARSE */
# define XSUM_SET_BINARY_MODE(file) { int const unused=_setmode(_fileno(file), _O_BINARY); (void)unused; }
# else
# define XSUM_SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
# endif
#else
# define XSUM_SET_BINARY_MODE(file) ((void)file)
#endif
XSUM_API int XSUM_isConsole(FILE* stream)
{
return XSUM_IS_CONSOLE(stream);
}
XSUM_API void XSUM_setBinaryMode(FILE* stream)
{
XSUM_SET_BINARY_MODE(stream);
}
#if !XSUM_WIN32_USE_WCHAR
XSUM_API FILE* XSUM_fopen(const char* filename, const char* mode)
{
return fopen(filename, mode);
}
XSUM_ATTRIBUTE((__format__(__printf__, 2, 0)))
XSUM_API int XSUM_vfprintf(FILE* stream, const char* format, va_list ap)
{
return vfprintf(stream, format, ap);
}
static int XSUM_stat(const char* infilename, XSUM_stat_t* statbuf)
{
#if defined(_MSC_VER)
return _stat64(infilename, statbuf);
#else
return stat(infilename, statbuf);
#endif
}
#ifndef XSUM_NO_MAIN
int main(int argc, const char* argv[])
{
#ifdef __OpenBSD__
/*
* xxhsum(1) does not create or write files, permit reading only.
*/
if (pledge("stdio rpath", NULL) == -1) {
XSUM_log("pledge: %s\n", strerror(errno));
return 1;
}
#endif
return XSUM_main(argc, argv);
}
#endif
/* Unicode helpers for Windows to make UTF-8 act as it should. */
#else
# include <windows.h>
# include <wchar.h>
/*****************************************************************************
* Unicode conversion tools
*****************************************************************************/
/*
* Converts a UTF-8 string to UTF-16. Acts like strdup. The string must be freed afterwards.
* This version allows keeping the output length.
*/
static wchar_t* XSUM_widenString(const char* str, int* lenOut)
{
int const len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
if (lenOut != NULL) *lenOut = len;
if (len == 0) return NULL;
{ wchar_t* buf = (wchar_t*)malloc((size_t)len * sizeof(wchar_t));
if (buf != NULL) {
if (MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, len) == 0) {
free(buf);
return NULL;
} }
return buf;
}
}
/*
* Converts a UTF-16 string to UTF-8. Acts like strdup. The string must be freed afterwards.
* This version allows keeping the output length.
*/
static char* XSUM_narrowString(const wchar_t *str, int *lenOut)
{
int len = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
if (lenOut != NULL) *lenOut = len;
if (len == 0) return NULL;
{ char* const buf = (char*)malloc((size_t)len * sizeof(char));
if (buf != NULL) {
if (WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, len, NULL, NULL) == 0) {
free(buf);
return NULL;
} }
return buf;
}
}
/*****************************************************************************
* File helpers
*****************************************************************************/
/*
* fopen wrapper that supports UTF-8
*
* fopen will only accept ANSI filenames, which means that we can't open Unicode filenames.
*
* In order to open a Unicode filename, we need to convert filenames to UTF-16 and use _wfopen.
*/
XSUM_API FILE* XSUM_fopen(const char* filename, const char* mode)
{
FILE* f = NULL;
wchar_t* const wide_filename = XSUM_widenString(filename, NULL);
if (wide_filename != NULL) {
wchar_t* const wide_mode = XSUM_widenString(mode, NULL);
if (wide_mode != NULL) {
f = _wfopen(wide_filename, wide_mode);
free(wide_mode);
}
free(wide_filename);
}
return f;
}
/*
* stat() wrapper which supports UTF-8 filenames.
*/
static int XSUM_stat(const char* infilename, XSUM_stat_t* statbuf)
{
int r = -1;
wchar_t* const wide_filename = XSUM_widenString(infilename, NULL);
if (wide_filename != NULL) {
r = _wstat64(wide_filename, statbuf);
free(wide_filename);
}
return r;
}
/*
* In case it isn't available, this is what MSVC 2019 defines in stdarg.h.
*/
#if defined(_MSC_VER) && !defined(__clang__) && !defined(va_copy)
# define XSUM_va_copy(destination, source) ((destination) = (source))
#else
# define XSUM_va_copy(destination, source) va_copy(destination, source)
#endif
/*
* vasprintf for Windows.
*/
XSUM_ATTRIBUTE((__format__(__printf__, 2, 0)))
static int XSUM_vasprintf(char** strp, const char* format, va_list ap)
{
int size;
va_list copy;
/*
* To be safe, make a va_copy.
*
* Note that Microsoft doesn't use va_copy in its sample code:
* https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/vsprintf-vsprintf-l-vswprintf-vswprintf-l-vswprintf-l?view=vs-2019
*/
XSUM_va_copy(copy, ap);
/* Calculate how many characters we need */
size = _vscprintf(format, ap);
va_end(copy);
if (size < 0) {
*strp = NULL;
return size;
} else {
int ret;
*strp = (char*) malloc((size_t)size + 1);
if (*strp == NULL) {
return -1;
}
/* vsprintf into the new buffer */
ret = vsprintf(*strp, format, ap);
if (ret < 0) {
free(*strp);
*strp = NULL;
}
return ret;
}
}
/*
* fprintf wrapper that supports UTF-8.
*
* fprintf doesn't properly handle Unicode on Windows.
*
* Additionally, it is codepage sensitive on console and may crash the program.
*
* Instead, we use vsnprintf, and either print with fwrite or convert to UTF-16
* for console output and use the codepage-independent WriteConsoleW.
*
* Credit to t-mat: https://github.com/t-mat/xxHash/commit/5691423
*/
XSUM_ATTRIBUTE((__format__(__printf__, 2, 0)))
XSUM_API int XSUM_vfprintf(FILE *stream, const char *format, va_list ap)
{
int result;
char* u8_str = NULL;
/*
* Generate the UTF-8 output string with vasprintf.
*/
result = XSUM_vasprintf(&u8_str, format, ap);
if (result >= 0) {
const size_t nchar = (size_t)result + 1;
/*
* Check if we are outputting to a console. Don't use XSUM_isConsole
* directly -- we don't need to call _get_osfhandle twice.
*/
int fileNb = _fileno(stream);
intptr_t handle_raw = _get_osfhandle(fileNb);
HANDLE handle = (HANDLE)handle_raw;
DWORD dwTemp;
if (handle_raw < 0) {
result = -1;
} else if (_isatty(fileNb) && GetConsoleMode(handle, &dwTemp)) {
/*
* Convert to UTF-16 and output with WriteConsoleW.
*
* This is codepage independent and works on Windows XP's default
* msvcrt.dll.
*/
int len;
wchar_t* const u16_buf = XSUM_widenString(u8_str, &len);
if (u16_buf == NULL) {
result = -1;
} else {
if (WriteConsoleW(handle, u16_buf, (DWORD)len - 1, &dwTemp, NULL)) {
result = (int)dwTemp;
} else {
result = -1;
}
free(u16_buf);
}
} else {
/* fwrite the UTF-8 string if we are printing to a file */
result = (int)fwrite(u8_str, 1, nchar - 1, stream);
if (result == 0) {
result = -1;
}
}
free(u8_str);
}
return result;
}
#ifndef XSUM_NO_MAIN
/*****************************************************************************
* Command Line argument parsing
*****************************************************************************/
/* Converts a UTF-16 argv to UTF-8. */
static char** XSUM_convertArgv(int argc, wchar_t* utf16_argv[])
{
char** const utf8_argv = (char**)malloc((size_t)(argc + 1) * sizeof(char*));
if (utf8_argv != NULL) {
int i;
for (i = 0; i < argc; i++) {
utf8_argv[i] = XSUM_narrowString(utf16_argv[i], NULL);
if (utf8_argv[i] == NULL) {
/* Out of memory, whoops. */
while (i-- > 0) {
free(utf8_argv[i]);
}
free(utf8_argv);
return NULL;
}
}
utf8_argv[argc] = NULL;
}
return utf8_argv;
}
/* Frees arguments returned by XSUM_convertArgv */
static void XSUM_freeArgv(int argc, char** argv)
{
int i;
if (argv == NULL) {
return;
}
for (i = 0; i < argc; i++) {
free(argv[i]);
}
free(argv);
}
static int XSUM_wmain(int argc, wchar_t* utf16_argv[])
{
/* Convert the UTF-16 arguments to UTF-8. */
char** utf8_argv = XSUM_convertArgv(argc, utf16_argv);
if (utf8_argv == NULL) {
/* An unfortunate but incredibly unlikely error. */
fprintf(stderr, "xxhsum: error converting command line arguments!\n");
abort();
} else {
int ret;
/*
* MinGW's terminal uses full block buffering for stderr.
*
* This is nonstandard behavior and causes text to not display until
* the buffer fills.
*
* `setvbuf()` can easily correct this to make text display instantly.
*/
setvbuf(stderr, NULL, _IONBF, 0);
/* Call our real main function */
ret = XSUM_main(argc, (void*)utf8_argv);
/* Cleanup */
XSUM_freeArgv(argc, utf8_argv);
return ret;
}
}
#if XSUM_WIN32_USE_WMAIN
/*
* The preferred method of obtaining the real UTF-16 arguments. Always works
* on MSVC, sometimes works on MinGW-w64 depending on the compiler flags.
*/
#ifdef __cplusplus
extern "C"
#endif
int __cdecl wmain(int argc, wchar_t* utf16_argv[])
{
return XSUM_wmain(argc, utf16_argv);
}
#else /* !XSUM_WIN32_USE_WMAIN */
/*
* Wrap `XSUM_wmain()` using `main()` and `__wgetmainargs()` on MinGW without
* Unicode support.
*
* `__wgetmainargs()` is used in the CRT startup to retrieve the arguments for
* `wmain()`, so we use it on MinGW to emulate `wmain()`.
*
* It is an internal function and not declared in any public headers, so we
* have to declare it manually.
*
* An alternative that doesn't mess with internal APIs is `GetCommandLineW()`
* with `CommandLineToArgvW()`, but the former doesn't expand wildcards and the
* latter requires linking to Shell32.dll and its numerous dependencies.
*
* This method keeps our dependencies to kernel32.dll and the CRT.
*
* https://docs.microsoft.com/en-us/cpp/c-runtime-library/getmainargs-wgetmainargs?view=vs-2019
*/
typedef struct {
int newmode;
} _startupinfo;
#ifdef __cplusplus
extern "C"
#endif
int __cdecl __wgetmainargs(
int* Argc,
wchar_t*** Argv,
wchar_t*** Env,
int DoWildCard,
_startupinfo* StartInfo
);
int main(int ansi_argc, const char* ansi_argv[])
{
int utf16_argc;
wchar_t** utf16_argv;
wchar_t** utf16_envp; /* Unused but required */
_startupinfo startinfo = {0}; /* 0 == don't change new mode */
/* Get wmain's UTF-16 arguments. Make sure we expand wildcards. */
if (__wgetmainargs(&utf16_argc, &utf16_argv, &utf16_envp, 1, &startinfo) < 0)
/* In the very unlikely case of an error, use the ANSI arguments. */
return XSUM_main(ansi_argc, ansi_argv);
/* Call XSUM_wmain with our UTF-16 arguments */
return XSUM_wmain(utf16_argc, utf16_argv);
}
#endif /* !XSUM_WIN32_USE_WMAIN */
#endif /* !XSUM_NO_MAIN */
#endif /* XSUM_WIN32_USE_WCHAR */
/*
* Determines whether the file at filename is a directory.
*/
XSUM_API int XSUM_isDirectory(const char* filename)
{
XSUM_stat_t statbuf;
int r = XSUM_stat(filename, &statbuf);
#ifdef _MSC_VER
if (!r && (statbuf.st_mode & _S_IFDIR)) return 1;
#else
if (!r && S_ISDIR(statbuf.st_mode)) return 1;
#endif
return 0;
}
/*
* Returns the filesize of the file at filename.
*/
XSUM_API XSUM_U64 XSUM_getFileSize(const char* filename)
{
XSUM_stat_t statbuf;
int r = XSUM_stat(filename, &statbuf);
if (r || !S_ISREG(statbuf.st_mode)) return 0; /* No good... */
return (XSUM_U64)statbuf.st_size;
}
+89
View File
@@ -0,0 +1,89 @@
/*
* xxhsum - Command line interface for xxhash algorithms
* Copyright (C) 2013-2021 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
#ifndef XSUM_OS_SPECIFIC_H
#define XSUM_OS_SPECIFIC_H
#include "xsum_config.h"
#include <stdio.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Declared here to be implemented in user code.
*
* Functions like main(), but is passed UTF-8 arguments even on Windows.
*/
XSUM_API int XSUM_main(int argc, const char* argv[]);
/*
* Returns whether stream is a console.
*
* Functionally equivalent to isatty(fileno(stream)).
*/
XSUM_API int XSUM_isConsole(FILE* stream);
/*
* Sets stream to pure binary mode (a.k.a. no CRLF conversions).
*/
XSUM_API void XSUM_setBinaryMode(FILE* stream);
/*
* Returns whether the file at filename is a directory.
*/
XSUM_API int XSUM_isDirectory(const char* filename);
/*
* Returns the file size of the file at filename.
*/
XSUM_API XSUM_U64 XSUM_getFileSize(const char* filename);
/*
* UTF-8 stdio wrappers primarily for Windows
*/
/*
* fopen() wrapper. Accepts UTF-8 filenames on Windows.
*
* Specifically, on Windows, the arguments will be converted to UTF-16
* and passed to _wfopen().
*/
XSUM_API FILE* XSUM_fopen(const char* filename, const char* mode);
/*
* vfprintf() wrapper which prints UTF-8 strings to Windows consoles
* if applicable.
*/
XSUM_ATTRIBUTE((__format__(__printf__, 2, 0)))
XSUM_API int XSUM_vfprintf(FILE* stream, const char* format, va_list ap);
#ifdef __cplusplus
}
#endif
#endif /* XSUM_OS_SPECIFIC_H */
+66
View File
@@ -0,0 +1,66 @@
/*
* xxhsum - Command line interface for xxhash algorithms
* Copyright (C) 2013-2021 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
#include "xsum_output.h"
#include "xsum_os_specific.h" /* XSUM_API */
int XSUM_logLevel = 2;
XSUM_ATTRIBUTE((__format__(__printf__, 1, 2)))
XSUM_API int XSUM_log(const char* format, ...)
{
int ret;
va_list ap;
va_start(ap, format);
ret = XSUM_vfprintf(stderr, format, ap);
va_end(ap);
return ret;
}
XSUM_ATTRIBUTE((__format__(__printf__, 1, 2)))
XSUM_API int XSUM_output(const char* format, ...)
{
int ret;
va_list ap;
va_start(ap, format);
ret = XSUM_vfprintf(stdout, format, ap);
va_end(ap);
return ret;
}
XSUM_ATTRIBUTE((__format__(__printf__, 2, 3)))
XSUM_API int XSUM_logVerbose(int minLevel, const char* format, ...)
{
if (XSUM_logLevel >= minLevel) {
int ret;
va_list ap;
va_start(ap, format);
ret = XSUM_vfprintf(stderr, format, ap);
va_end(ap);
return ret;
}
return 0;
}
+62
View File
@@ -0,0 +1,62 @@
/*
* xxhsum - Command line interface for xxhash algorithms
* Copyright (C) 2013-2021 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
#ifndef XSUM_OUTPUT_H
#define XSUM_OUTPUT_H
#include "xsum_config.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* How verbose the output is.
*/
extern int XSUM_logLevel;
/*
* Same as fprintf(stderr, format, ...)
*/
XSUM_ATTRIBUTE((__format__(__printf__, 1, 2)))
XSUM_API int XSUM_log(const char *format, ...);
/*
* Like XSUM_log, but only outputs if XSUM_logLevel >= minLevel.
*/
XSUM_ATTRIBUTE((__format__(__printf__, 2, 3)))
XSUM_API int XSUM_logVerbose(int minLevel, const char *format, ...);
/*
* Same as printf(format, ...)
*/
XSUM_ATTRIBUTE((__format__(__printf__, 1, 2)))
XSUM_API int XSUM_output(const char *format, ...);
#ifdef __cplusplus
}
#endif
#endif /* XSUM_OUTPUT_H */
+733
View File
@@ -0,0 +1,733 @@
/*
* xxhsum - Command line interface for xxhash algorithms
* Copyright (C) 2013-2021 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
#include "xsum_sanity_check.h"
#include "xsum_output.h" /* XSUM_log */
#ifndef XXH_STATIC_LINKING_ONLY
# define XXH_STATIC_LINKING_ONLY
#endif
#include "../xxhash.h"
#include <stdlib.h> /* exit */
#include <assert.h>
#include <string.h> /* memcmp */
/* use #define to make them constant, required for initialization */
#define PRIME32 2654435761U
#define PRIME64 11400714785074694797ULL
/*
* Fills a test buffer with pseudorandom data.
*
* This is used in the sanity check - its values must not be changed.
*/
XSUM_API void XSUM_fillTestBuffer(XSUM_U8* buffer, size_t len)
{
XSUM_U64 byteGen = PRIME32;
size_t i;
assert(buffer != NULL);
for (i=0; i<len; i++) {
buffer[i] = (XSUM_U8)(byteGen>>56);
byteGen *= PRIME64;
}
}
/* ************************************************
* Self-test:
* ensure results consistency across platforms
*********************************************** */
#if XSUM_NO_TESTS
XSUM_API void XSUM_sanityCheck(void)
{
XSUM_log("This version of xxhsum is not verified.\n");
}
#else
/*
* Test data vectors
*/
typedef struct {
XSUM_U32 len;
XSUM_U32 seed;
XSUM_U32 Nresult;
} XSUM_testdata32_t;
typedef struct {
XSUM_U32 len;
XSUM_U64 seed;
XSUM_U64 Nresult;
} XSUM_testdata64_t;
typedef struct {
XSUM_U32 len;
XSUM_U64 seed;
XXH128_hash_t Nresult;
} XSUM_testdata128_t;
#define SECRET_SAMPLE_NBBYTES 5
typedef struct {
XSUM_U32 seedLen;
XSUM_U32 secretLen;
XSUM_U8 byte[SECRET_SAMPLE_NBBYTES];
} XSUM_testdata_sample_t;
/* XXH32 */
static const XSUM_testdata32_t XSUM_XXH32_testdata[] = {
{ 0, 0, 0x02CC5D05U },
{ 0, PRIME32, 0x36B78AE7U },
{ 1, 0, 0xCF65B03EU },
{ 1, PRIME32, 0xB4545AA4U },
{ 14, 0, 0x1208E7E2U },
{ 14, PRIME32, 0x6AF1D1FEU },
{ 222, 0, 0x5BD11DBDU },
{ 222, PRIME32, 0x58803C5FU }
};
/* XXH64 */
static const XSUM_testdata64_t XSUM_XXH64_testdata[] = {
{ 0, 0, 0xEF46DB3751D8E999ULL },
{ 0, PRIME32, 0xAC75FDA2929B17EFULL },
{ 1, 0, 0xE934A84ADB052768ULL },
{ 1, PRIME32, 0x5014607643A9B4C3ULL },
{ 4, 0, 0x9136A0DCA57457EEULL },
{ 14, 0, 0x8282DCC4994E35C8ULL },
{ 14, PRIME32, 0xC3BD6BF63DEB6DF0ULL },
{ 222, 0, 0xB641AE8CB691C174ULL },
{ 222, PRIME32, 0x20CB8AB7AE10C14AULL }
};
/*
* XXH3:
* Due to being a more complex hash function with specializations for certain
* lengths, a more extensive test is used for XXH3.
*/
/* XXH3_64bits, seeded */
static const XSUM_testdata64_t XSUM_XXH3_testdata[] = {
{ 0, 0, 0x2D06800538D394C2ULL }, /* empty string */
{ 0, PRIME64, 0xA8A6B918B2F0364AULL },
{ 1, 0, 0xC44BDFF4074EECDBULL }, /* 1 - 3 */
{ 1, PRIME64, 0x032BE332DD766EF8ULL },
{ 6, 0, 0x27B56A84CD2D7325ULL }, /* 4 - 8 */
{ 6, PRIME64, 0x84589C116AB59AB9ULL },
{ 12, 0, 0xA713DAF0DFBB77E7ULL }, /* 9 - 16 */
{ 12, PRIME64, 0xE7303E1B2336DE0EULL },
{ 24, 0, 0xA3FE70BF9D3510EBULL }, /* 17 - 32 */
{ 24, PRIME64, 0x850E80FC35BDD690ULL },
{ 48, 0, 0x397DA259ECBA1F11ULL }, /* 33 - 64 */
{ 48, PRIME64, 0xADC2CBAA44ACC616ULL },
{ 80, 0, 0xBCDEFBBB2C47C90AULL }, /* 65 - 96 */
{ 80, PRIME64, 0xC6DD0CB699532E73ULL },
{ 195, 0, 0xCD94217EE362EC3AULL }, /* 129-240 */
{ 195, PRIME64, 0xBA68003D370CB3D9ULL },
{ 403, 0, 0xCDEB804D65C6DEA4ULL }, /* one block, last stripe is overlapping */
{ 403, PRIME64, 0x6259F6ECFD6443FDULL },
{ 512, 0, 0x617E49599013CB6BULL }, /* one block, finishing at stripe boundary */
{ 512, PRIME64, 0x3CE457DE14C27708ULL },
{ 2048, 0, 0xDD59E2C3A5F038E0ULL }, /* 2 blocks, finishing at block boundary */
{ 2048, PRIME64, 0x66F81670669ABABCULL },
{ 2099, 0, 0xC6B9D9B3FC9AC765ULL }, /* 2 blocks + 1 partial block, to detect off-by-one scrambling issues, like #816 */
{ 2099, PRIME64, 0x184F316843663974ULL },
{ 2240, 0, 0x6E73A90539CF2948ULL }, /* 3 blocks, finishing at stripe boundary */
{ 2240, PRIME64, 0x757BA8487D1B5247ULL },
{ 2367, 0, 0xCB37AEB9E5D361EDULL }, /* 3 blocks, last stripe is overlapping */
{ 2367, PRIME64, 0xD2DB3415B942B42AULL }
};
/* XXH3_64bits, custom secret */
static const XSUM_testdata64_t XSUM_XXH3_withSecret_testdata[] = {
{ 0, 0, 0x3559D64878C5C66CULL }, /* empty string */
{ 1, 0, 0x8A52451418B2DA4DULL }, /* 1 - 3 */
{ 6, 0, 0x82C90AB0519369ADULL }, /* 4 - 8 */
{ 12, 0, 0x14631E773B78EC57ULL }, /* 9 - 16 */
{ 24, 0, 0xCDD5542E4A9D9FE8ULL }, /* 17 - 32 */
{ 48, 0, 0x33ABD54D094B2534ULL }, /* 33 - 64 */
{ 80, 0, 0xE687BA1684965297ULL }, /* 65 - 96 */
{ 195, 0, 0xA057273F5EECFB20ULL }, /* 129-240 */
{ 403, 0, 0x14546019124D43B8ULL }, /* one block, last stripe is overlapping */
{ 512, 0, 0x7564693DD526E28DULL }, /* one block, finishing at stripe boundary */
{ 2048, 0, 0xD32E975821D6519FULL }, /* >= 2 blodcks, at least one scrambling */
{ 2367, 0, 0x293FA8E5173BB5E7ULL }, /* >= 2 blocks, at least one scrambling, last stripe unaligned */
{ 64*10*3, 0, 0x751D2EC54BC6038BULL } /* exactly 3 full blocks, not a multiple of 256 */
};
/* XXH3_128bits, seeded */
static const XSUM_testdata128_t XSUM_XXH128_testdata[] = {
{ 0, 0, { 0x6001C324468D497FULL, 0x99AA06D3014798D8ULL } }, /* empty string */
{ 0, PRIME32, { 0x5444F7869C671AB0ULL, 0x92220AE55E14AB50ULL } },
{ 1, 0, { 0xC44BDFF4074EECDBULL, 0xA6CD5E9392000F6AULL } }, /* 1 - 3 */
{ 1, PRIME32, { 0xB53D5557E7F76F8DULL, 0x89B99554BA22467CULL } },
{ 6, 0, { 0x3E7039BDDA43CFC6ULL, 0x082AFE0B8162D12AULL } }, /* 4 - 8 */
{ 6, PRIME32, { 0x269D8F70BE98856EULL, 0x5A865B5389ABD2B1ULL } },
{ 12, 0, { 0x061A192713F69AD9ULL, 0x6E3EFD8FC7802B18ULL } }, /* 9 - 16 */
{ 12, PRIME32, { 0x9BE9F9A67F3C7DFBULL, 0xD7E09D518A3405D3ULL } },
{ 24, 0, { 0x1E7044D28B1B901DULL, 0x0CE966E4678D3761ULL } }, /* 17 - 32 */
{ 24, PRIME32, { 0xD7304C54EBAD40A9ULL, 0x3162026714A6A243ULL } },
{ 48, 0, { 0xF942219AED80F67BULL, 0xA002AC4E5478227EULL } }, /* 33 - 64 */
{ 48, PRIME32, { 0x7BA3C3E453A1934EULL, 0x163ADDE36C072295ULL } },
{ 81, 0, { 0x5E8BAFB9F95FB803ULL, 0x4952F58181AB0042ULL } }, /* 65 - 96 */
{ 81, PRIME32, { 0x703FBB3D7A5F755CULL, 0x2724EC7ADC750FB6ULL } },
{ 222, 0, { 0xF1AEBD597CEC6B3AULL, 0x337E09641B948717ULL } }, /* 129-240 */
{ 222, PRIME32, { 0xAE995BB8AF917A8DULL, 0x91820016621E97F1ULL } },
{ 403, 0, { 0xCDEB804D65C6DEA4ULL, 0x1B6DE21E332DD73DULL } }, /* one block, last stripe is overlapping */
{ 403, PRIME64, { 0x6259F6ECFD6443FDULL, 0xBED311971E0BE8F2ULL } },
{ 512, 0, { 0x617E49599013CB6BULL, 0x18D2D110DCC9BCA1ULL } }, /* one block, finishing at stripe boundary */
{ 512, PRIME64, { 0x3CE457DE14C27708ULL, 0x925D06B8EC5B8040ULL } },
{ 2048, 0, { 0xDD59E2C3A5F038E0ULL, 0xF736557FD47073A5ULL } }, /* 2 blocks, finishing at block boundary */
{ 2048, PRIME32, { 0x230D43F30206260BULL, 0x7FB03F7E7186C3EAULL } },
{ 2240, 0, { 0x6E73A90539CF2948ULL, 0xCCB134FBFA7CE49DULL } }, /* 3 blocks, finishing at stripe boundary */
{ 2240, PRIME32, { 0xED385111126FBA6FULL, 0x50A1FE17B338995FULL } },
{ 2367, 0, { 0xCB37AEB9E5D361EDULL, 0xE89C0F6FF369B427ULL } }, /* 3 blocks, last stripe is overlapping */
{ 2367, PRIME32, { 0x6F5360AE69C2F406ULL, 0xD23AAE4B76C31ECBULL } }
};
/* XXH128, custom secret */
static const XSUM_testdata128_t XSUM_XXH128_withSecret_testdata[] = {
{ 0, 0, { 0x005923CCEECBE8AEULL, 0x5F70F4EA232F1D38ULL } }, /* empty string */
{ 1, 0, { 0x8A52451418B2DA4DULL, 0x3A66AF5A9819198EULL } }, /* 1 - 3 */
{ 6, 0, { 0x0B61C8ACA7D4778FULL, 0x376BD91B6432F36DULL } }, /* 4 - 8 */
{ 12, 0, { 0xAF82F6EBA263D7D8ULL, 0x90A3C2D839F57D0FULL } } /* 9 - 16 */
};
#define SECRET_SIZE_MAX 9867
static const XSUM_testdata_sample_t XSUM_XXH3_generateSecret_testdata[] = {
{ 0, 192, { 0xE7, 0x8C, 0x77, 0x77, 0x00 } },
{ 1, 240, { 0x2B, 0x3E, 0xDE, 0xC1, 0x00 } },
{ XXH3_SECRET_SIZE_MIN - 1, 277, { 0xE8, 0x39, 0x6C, 0xCC, 0x7B } },
{ XXH3_SECRET_DEFAULT_SIZE + 500, SECRET_SIZE_MAX, { 0xD6, 0x1C, 0x41, 0x17, 0xB3 } }
};
static void XSUM_checkResult32(XXH32_hash_t r1, XXH32_hash_t r2)
{
static int nbTests = 1;
if (r1!=r2) {
XSUM_log("\rError: 32-bit hash test %i: Internal sanity check failed!\n", nbTests);
XSUM_log("\rGot 0x%08X, expected 0x%08X.\n", (unsigned)r1, (unsigned)r2);
XSUM_log("\rNote: If you modified the hash functions, make sure to either update the values\n"
"or temporarily recompile with XSUM_NO_TESTS=1.\n");
exit(1);
}
nbTests++;
}
static void XSUM_checkResult64(XXH64_hash_t r1, XXH64_hash_t r2)
{
static int nbTests = 1;
if (r1!=r2) {
XSUM_log("\rError: 64-bit hash test %i: Internal sanity check failed!\n", nbTests);
XSUM_log("\rGot 0x%08X%08XULL, expected 0x%08X%08XULL.\n",
(unsigned)(r1>>32), (unsigned)r1, (unsigned)(r2>>32), (unsigned)r2);
XSUM_log("\rNote: If you modified the hash functions, make sure to either update the values\n"
"or temporarily recompile with XSUM_NO_TESTS=1.\n");
exit(1);
}
nbTests++;
}
static void XSUM_checkResult128(XXH128_hash_t r1, XXH128_hash_t r2)
{
static int nbTests = 1;
if ((r1.low64 != r2.low64) || (r1.high64 != r2.high64)) {
XSUM_log("\rError: 128-bit hash test %i: Internal sanity check failed.\n", nbTests);
XSUM_log("\rGot { 0x%08X%08XULL, 0x%08X%08XULL }, expected { 0x%08X%08XULL, 0x%08X%08XULL } \n",
(unsigned)(r1.low64>>32), (unsigned)r1.low64, (unsigned)(r1.high64>>32), (unsigned)r1.high64,
(unsigned)(r2.low64>>32), (unsigned)r2.low64, (unsigned)(r2.high64>>32), (unsigned)r2.high64 );
XSUM_log("\rNote: If you modified the hash functions, make sure to either update the values\n"
"or temporarily recompile with XSUM_NO_TESTS=1.\n");
exit(1);
}
nbTests++;
}
static void XSUM_testXXH32(const void* data, const XSUM_testdata32_t* testData)
{
XXH32_state_t *state = XXH32_createState();
size_t pos;
size_t len = testData->len;
XSUM_U32 seed = testData->seed;
XSUM_U32 Nresult = testData->Nresult;
if (len == 0) {
data = NULL;
} else {
assert(data != NULL);
}
assert(state != NULL);
XSUM_checkResult32(XXH32(data, len, seed), Nresult);
(void)XXH32_reset(state, seed);
(void)XXH32_update(state, data, len);
XSUM_checkResult32(XXH32_digest(state), Nresult);
(void)XXH32_reset(state, seed);
for (pos=0; pos<len; pos++)
(void)XXH32_update(state, ((const char*)data)+pos, 1);
XSUM_checkResult32(XXH32_digest(state), Nresult);
XXH32_freeState(state);
}
static void XSUM_testXXH64(const void* data, const XSUM_testdata64_t* testData)
{
XXH64_state_t *state = XXH64_createState();
size_t pos;
size_t len = (size_t)testData->len;
XSUM_U64 seed = testData->seed;
XSUM_U64 Nresult = testData->Nresult;
if (len == 0) {
data = NULL;
} else {
assert(data != NULL);
}
assert(state != NULL);
XSUM_checkResult64(XXH64(data, len, seed), Nresult);
(void)XXH64_reset(state, seed);
(void)XXH64_update(state, data, len);
XSUM_checkResult64(XXH64_digest(state), Nresult);
(void)XXH64_reset(state, seed);
for (pos=0; pos<len; pos++)
(void)XXH64_update(state, ((const char*)data)+pos, 1);
XSUM_checkResult64(XXH64_digest(state), Nresult);
XXH64_freeState(state);
}
/*
* Used to get "random" (but actually 100% reproducible) lengths for
* XSUM_XXH3_randomUpdate.
*/
static XSUM_U32 XSUM_rand(void)
{
static XSUM_U64 seed = PRIME32;
seed *= PRIME64;
return (XSUM_U32)(seed >> 40);
}
/*
* Technically, XXH3_64bits_update is identical to XXH3_128bits_update as of
* v0.8.0, but we treat them as separate.
*/
typedef XXH_errorcode (*XSUM_XXH3_update_t)(XXH3_state_t* state, const void* input, size_t length);
/*
* Runs the passed XXH3_update variant on random lengths. This is to test the
* more complex logic of the update function, catching bugs like this one:
* https://github.com/Cyan4973/xxHash/issues/378
*/
static void XSUM_XXH3_randomUpdate(XXH3_state_t* state, const void* data,
size_t len, XSUM_XXH3_update_t update_fn)
{
size_t p = 0;
while (p < len) {
size_t const modulo = len > 2 ? len : 2;
size_t l = (size_t)(XSUM_rand()) % modulo;
if (p + l > len) l = len - p;
(void)update_fn(state, (const char*)data+p, l);
p += l;
}
}
static void XSUM_testXXH3(const void* data, const XSUM_testdata64_t* testData)
{
size_t len = testData->len;
XSUM_U64 seed = testData->seed;
XSUM_U64 Nresult = testData->Nresult;
if (len == 0) {
data = NULL;
} else {
assert(data != NULL);
}
{ XSUM_U64 const Dresult = XXH3_64bits_withSeed(data, len, seed);
XSUM_checkResult64(Dresult, Nresult);
}
/* check that the no-seed variant produces same result as seed==0 */
if (seed == 0) {
XSUM_U64 const Dresult = XXH3_64bits(data, len);
XSUM_checkResult64(Dresult, Nresult);
}
/* check that the combination of
* XXH3_generateSecret_fromSeed() and XXH3_64bits_withSecretandSeed()
* results in exactly the same hash generation as XXH3_64bits_withSeed() */
{ char secretBuffer[XXH3_SECRET_DEFAULT_SIZE+1];
char* const secret = secretBuffer + 1; /* intentional unalignment */
XXH3_generateSecret_fromSeed(secret, seed);
{ XSUM_U64 const Dresult = XXH3_64bits_withSecretandSeed(data, len, secret, XXH3_SECRET_DEFAULT_SIZE, seed);
XSUM_checkResult64(Dresult, Nresult);
}
/* check that XXH3_64bits_withSecretandSeed()
* results in exactly the same return value as XXH3_64bits_withSeed()
* when len <= XXH3_MIDSIZE_MAX, whatever the content of @secret */
memset(secret, 0x99, 9);
if (len <= XXH3_MIDSIZE_MAX) {
XSUM_U64 const Dresult = XXH3_64bits_withSecretandSeed(data, len, secret, XXH3_SECRET_DEFAULT_SIZE, seed);
XSUM_checkResult64(Dresult, Nresult);
}
}
/* streaming API test */
{ XXH3_state_t* const state = XXH3_createState();
assert(state != NULL);
/* single ingestion */
(void)XXH3_64bits_reset_withSeed(state, seed);
(void)XXH3_64bits_update(state, data, len);
XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
/* random ingestion */
(void)XXH3_64bits_reset_withSeed(state, seed);
XSUM_XXH3_randomUpdate(state, data, len, &XXH3_64bits_update);
XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
/* byte by byte ingestion */
{ size_t pos;
(void)XXH3_64bits_reset_withSeed(state, seed);
for (pos=0; pos<len; pos++)
(void)XXH3_64bits_update(state, ((const char*)data)+pos, 1);
XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
}
/* check that streaming with a combination of
* XXH3_generateSecret_fromSeed() and XXH3_64bits_reset_withSecretandSeed()
* results in exactly the same hash generation as XXH3_64bits_reset_withSeed() */
{ char secretBuffer[XXH3_SECRET_DEFAULT_SIZE+1];
char* const secret = secretBuffer + 1; /* intentional unalignment */
XXH3_generateSecret_fromSeed(secret, seed);
/* single ingestion */
(void)XXH3_64bits_reset_withSecretandSeed(state, secret, XXH3_SECRET_DEFAULT_SIZE, seed);
(void)XXH3_64bits_update(state, data, len);
XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
/* check that XXH3_64bits_withSecretandSeed()
* results in exactly the same return value as XXH3_64bits_withSeed()
* when len <= XXH3_MIDSIZE_MAX, whatever the content of @secret */
if (len <= XXH3_MIDSIZE_MAX) {
/* single ingestion */
memset(secret, 0x99, 9);
(void)XXH3_64bits_reset_withSecretandSeed(state, secret, XXH3_SECRET_DEFAULT_SIZE, seed);
(void)XXH3_64bits_update(state, data, len);
XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
}
}
XXH3_freeState(state);
}
}
static void XSUM_testXXH3_withSecret(const void* data, const void* secret,
size_t secretSize, const XSUM_testdata64_t* testData)
{
size_t len = (size_t)testData->len;
XSUM_U64 Nresult = testData->Nresult;
if (len == 0) {
data = NULL;
} else {
assert(data != NULL);
}
{ XSUM_U64 const Dresult = XXH3_64bits_withSecret(data, len, secret, secretSize);
XSUM_checkResult64(Dresult, Nresult);
}
/* check that XXH3_64bits_withSecretandSeed()
* results in exactly the same return value as XXH3_64bits_withSecret() */
if (len > XXH3_MIDSIZE_MAX)
{ XSUM_U64 const Dresult = XXH3_64bits_withSecretandSeed(data, len, secret, secretSize, 0);
XSUM_checkResult64(Dresult, Nresult);
}
/* streaming API test */
{ XXH3_state_t *state = XXH3_createState();
assert(state != NULL);
(void)XXH3_64bits_reset_withSecret(state, secret, secretSize);
(void)XXH3_64bits_update(state, data, len);
XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
/* random ingestion */
(void)XXH3_64bits_reset_withSecret(state, secret, secretSize);
XSUM_XXH3_randomUpdate(state, data, len, &XXH3_64bits_update);
XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
/* byte by byte ingestion */
{ size_t pos;
(void)XXH3_64bits_reset_withSecret(state, secret, secretSize);
for (pos=0; pos<len; pos++)
(void)XXH3_64bits_update(state, ((const char*)data)+pos, 1);
XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
}
/* check that XXH3_64bits_reset_withSecretandSeed()
* results in exactly the same return value as XXH3_64bits_reset_withSecret()
* when len > XXH3_MIDSIZE_MAX, whatever the value of @seed */
if (len > XXH3_MIDSIZE_MAX) {
/* single ingestion */
(void)XXH3_64bits_reset_withSecretandSeed(state, secret, secretSize, 17);
(void)XXH3_64bits_update(state, data, len);
XSUM_checkResult64(XXH3_64bits_digest(state), Nresult);
}
XXH3_freeState(state);
}
}
static void XSUM_testXXH128(const void* data, const XSUM_testdata128_t* testData)
{
size_t len = (size_t)testData->len;
XSUM_U64 seed = testData->seed;
XXH128_hash_t const Nresult = testData->Nresult;
if (len == 0) {
data = NULL;
} else {
assert(data != NULL);
}
{ XXH128_hash_t const Dresult = XXH3_128bits_withSeed(data, len, seed);
XSUM_checkResult128(Dresult, Nresult);
}
/* check that XXH128() is identical to XXH3_128bits_withSeed() */
{ XXH128_hash_t const Dresult2 = XXH128(data, len, seed);
XSUM_checkResult128(Dresult2, Nresult);
}
/* check that the no-seed variant produces same result as seed==0 */
if (seed == 0) {
XXH128_hash_t const Dresult = XXH3_128bits(data, len);
XSUM_checkResult128(Dresult, Nresult);
}
/* check that the combination of
* XXH3_generateSecret_fromSeed() and XXH3_128bits_withSecretandSeed()
* results in exactly the same hash generation as XXH3_64bits_withSeed() */
{ char secretBuffer[XXH3_SECRET_DEFAULT_SIZE+1];
char* const secret = secretBuffer + 1; /* intentional unalignment */
XXH3_generateSecret_fromSeed(secret, seed);
{ XXH128_hash_t const Dresult = XXH3_128bits_withSecretandSeed(data, len, secret, XXH3_SECRET_DEFAULT_SIZE, seed);
XSUM_checkResult128(Dresult, Nresult);
}
/* check that XXH3_128bits_withSecretandSeed()
* results in exactly the same return value as XXH3_128bits_withSeed()
* if len <= XXH3_MIDSIZE_MAX, whatever the content of @secret */
memset(secret, 0x99, 9);
if (len <= XXH3_MIDSIZE_MAX) {
XXH128_hash_t const Dresult = XXH3_128bits_withSecretandSeed(data, len, secret, XXH3_SECRET_DEFAULT_SIZE, seed);
XSUM_checkResult128(Dresult, Nresult);
}
}
/* streaming API test */
{ XXH3_state_t *state = XXH3_createState();
assert(state != NULL);
/* single ingestion */
(void)XXH3_128bits_reset_withSeed(state, seed);
(void)XXH3_128bits_update(state, data, len);
XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
/* random ingestion */
(void)XXH3_128bits_reset_withSeed(state, seed);
XSUM_XXH3_randomUpdate(state, data, len, &XXH3_128bits_update);
XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
/* byte by byte ingestion */
{ size_t pos;
(void)XXH3_128bits_reset_withSeed(state, seed);
for (pos=0; pos<len; pos++)
(void)XXH3_128bits_update(state, ((const char*)data)+pos, 1);
XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
}
/* check that streaming with a combination of
* XXH3_generateSecret_fromSeed() and XXH3_128bits_reset_withSecretandSeed()
* results in exactly the same hash generation as XXH3_128bits_reset_withSeed() */
{ char secretBuffer[XXH3_SECRET_DEFAULT_SIZE+1];
char* const secret = secretBuffer + 1; /* intentional unalignment */
XXH3_generateSecret_fromSeed(secret, seed);
/* single ingestion */
(void)XXH3_128bits_reset_withSecretandSeed(state, secret, XXH3_SECRET_DEFAULT_SIZE, seed);
(void)XXH3_128bits_update(state, data, len);
XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
/* check that XXH3_128bits_reset_withSecretandSeed()
* results in exactly the same return value as XXH3_128bits_reset_withSeed()
* if len <= XXH3_MIDSIZE_MAX, whatever the content of @secret */
if (len <= XXH3_MIDSIZE_MAX) {
/* single ingestion */
memset(secret, 0x99, 9);
(void)XXH3_128bits_reset_withSecretandSeed(state, secret, XXH3_SECRET_DEFAULT_SIZE, seed);
(void)XXH3_128bits_update(state, data, len);
XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
}
}
XXH3_freeState(state);
}
}
static void XSUM_testXXH128_withSecret(const void* data, const void* secret, size_t secretSize, const XSUM_testdata128_t* testData)
{
size_t len = testData->len;
XXH128_hash_t Nresult = testData->Nresult;
if (len == 0) {
data = NULL;
} else {
assert(data != NULL);
}
{ XXH128_hash_t const Dresult = XXH3_128bits_withSecret(data, len, secret, secretSize);
XSUM_checkResult128(Dresult, Nresult);
}
/* check that XXH3_128bits_withSecretandSeed()
* results in exactly the same return value as XXH3_128bits_withSecret() */
if (len > XXH3_MIDSIZE_MAX)
{ XXH128_hash_t const Dresult = XXH3_128bits_withSecretandSeed(data, len, secret, secretSize, 0);
XSUM_checkResult128(Dresult, Nresult);
}
/* streaming API test */
{ XXH3_state_t* const state = XXH3_createState();
assert(state != NULL);
(void)XXH3_128bits_reset_withSecret(state, secret, secretSize);
(void)XXH3_128bits_update(state, data, len);
XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
/* random ingestion */
(void)XXH3_128bits_reset_withSecret(state, secret, secretSize);
XSUM_XXH3_randomUpdate(state, data, len, &XXH3_128bits_update);
XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
/* byte by byte ingestion */
{ size_t pos;
(void)XXH3_128bits_reset_withSecret(state, secret, secretSize);
for (pos=0; pos<len; pos++)
(void)XXH3_128bits_update(state, ((const char*)data)+pos, 1);
XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
}
/* check that XXH3_128bits_reset_withSecretandSeed()
* results in exactly the same return value as XXH3_128bits_reset_withSecret() */
if (len > XXH3_MIDSIZE_MAX) {
/* single ingestion */
(void)XXH3_128bits_reset_withSecretandSeed(state, secret, secretSize, 0);
(void)XXH3_128bits_update(state, data, len);
XSUM_checkResult128(XXH3_128bits_digest(state), Nresult);
}
XXH3_freeState(state);
}
}
static void XSUM_testSecretGenerator(const void* customSeed, const XSUM_testdata_sample_t* testData)
{
static int nbTests = 1;
const int sampleIndex[SECRET_SAMPLE_NBBYTES] = { 0, 62, 131, 191, 241 }; /* position of sampled bytes */
XSUM_U8 secretBuffer[SECRET_SIZE_MAX] = {0};
XSUM_U8 samples[SECRET_SAMPLE_NBBYTES];
int i;
assert(testData->secretLen <= SECRET_SIZE_MAX);
XXH3_generateSecret(secretBuffer, testData->secretLen, customSeed, testData->seedLen);
for (i=0; i<SECRET_SAMPLE_NBBYTES; i++) {
samples[i] = secretBuffer[sampleIndex[i]];
}
if (memcmp(samples, testData->byte, sizeof(testData->byte))) {
XSUM_log("\rError: Secret generation test %i: Internal sanity check failed. \n", nbTests);
XSUM_log("\rGot { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X }, expected { 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X } \n",
samples[0], samples[1], samples[2], samples[3], samples[4],
testData->byte[0], testData->byte[1], testData->byte[2], testData->byte[3], testData->byte[4] );
exit(1);
}
nbTests++;
}
/*!
* XSUM_sanityCheck():
* Runs a sanity check before the benchmark.
*
* Exits on an incorrect output.
*/
XSUM_API void XSUM_sanityCheck(void)
{
size_t i;
#define SANITY_BUFFER_SIZE 2367
XSUM_U8 sanityBuffer[SANITY_BUFFER_SIZE];
const void* const secret = sanityBuffer + 7;
const size_t secretSize = XXH3_SECRET_SIZE_MIN + 11;
assert(sizeof(sanityBuffer) >= 7 + secretSize);
XSUM_fillTestBuffer(sanityBuffer, sizeof(sanityBuffer));
/* XXH32 */
for (i = 0; i < (sizeof(XSUM_XXH32_testdata)/sizeof(XSUM_XXH32_testdata[0])); i++) {
XSUM_testXXH32(sanityBuffer, &XSUM_XXH32_testdata[i]);
}
/* XXH64 */
for (i = 0; i < (sizeof(XSUM_XXH64_testdata)/sizeof(XSUM_XXH64_testdata[0])); i++) {
XSUM_testXXH64(sanityBuffer, &XSUM_XXH64_testdata[i]);
}
/* XXH3_64bits, seeded */
for (i = 0; i < (sizeof(XSUM_XXH3_testdata)/sizeof(XSUM_XXH3_testdata[0])); i++) {
XSUM_testXXH3(sanityBuffer, &XSUM_XXH3_testdata[i]);
}
/* XXH3_64bits, custom secret */
for (i = 0; i < (sizeof(XSUM_XXH3_withSecret_testdata)/sizeof(XSUM_XXH3_withSecret_testdata[0])); i++) {
XSUM_testXXH3_withSecret(sanityBuffer, secret, secretSize, &XSUM_XXH3_withSecret_testdata[i]);
}
/* XXH128 */
for (i = 0; i < (sizeof(XSUM_XXH128_testdata)/sizeof(XSUM_XXH128_testdata[0])); i++) {
XSUM_testXXH128(sanityBuffer, &XSUM_XXH128_testdata[i]);
}
/* XXH128 with custom Secret */
for (i = 0; i < (sizeof(XSUM_XXH128_withSecret_testdata)/sizeof(XSUM_XXH128_withSecret_testdata[0])); i++) {
XSUM_testXXH128_withSecret(sanityBuffer, secret, secretSize, &XSUM_XXH128_withSecret_testdata[i]);
}
/* secret generator */
for (i = 0; i < (sizeof(XSUM_XXH3_generateSecret_testdata)/sizeof(XSUM_XXH3_generateSecret_testdata[0])); i++) {
assert(XSUM_XXH3_generateSecret_testdata[i].seedLen <= SANITY_BUFFER_SIZE);
XSUM_testSecretGenerator(sanityBuffer, &XSUM_XXH3_generateSecret_testdata[i]);
}
XSUM_logVerbose(3, "\r%70s\r", ""); /* Clean display line */
XSUM_logVerbose(3, "Sanity check -- all tests ok\n");
}
#endif /* !XSUM_NO_TESTS */
+60
View File
@@ -0,0 +1,60 @@
/*
* xxhsum - Command line interface for xxhash algorithms
* Copyright (C) 2013-2021 Yann Collet
*
* GPL v2 License
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
#ifndef XSUM_SANITY_CHECK_H
#define XSUM_SANITY_CHECK_H
#include "xsum_config.h" /* XSUM_API, XSUM_U8 */
#include <stddef.h> /* size_t */
#ifdef __cplusplus
extern "C" {
#endif
/*
* Runs a series of self-tests.
*
* Exits if any of these tests fail, printing a message to stderr.
*
* If XSUM_NO_TESTS is defined to non-zero,
* this will instead print a warning if this is called (e.g. via xxhsum -b).
*/
XSUM_API void XSUM_sanityCheck(void);
/*
* Fills a test buffer with pseudorandom data.
*
* This is used in the sanity check and the benchmarks.
* Its values must not be changed.
*/
XSUM_API void XSUM_fillTestBuffer(XSUM_U8* buffer, size_t len);
#ifdef __cplusplus
}
#endif
#endif /* XSUM_SANITY_CHECK_H */
@@ -1,35 +1,40 @@
.
.TH "XXHSUM" "1" "December 2019" "xxhsum 0.7.2" "User Commands"
.TH "XXHSUM" "1" "May 2024" "xxhsum 0.8.3" "User Commands"
.
.SH "NAME"
\fBxxhsum\fR \- print or check xxHash non\-cryptographic checksums
.
.SH "SYNOPSIS"
\fBxxhsum [<OPTION>]\.\.\. [<FILE>]\.\.\.\fR
.
.br
\fBxxhsum \-b [<OPTION>]\.\.\.\fR
\fBxxhsum\fR [\fIOPTION\fR]\.\.\. [\fIFILE\fR]\.\.\. \fBxxhsum \-b\fR [\fIOPTION\fR]\.\.\.
.
.P
\fBxxh32sum\fR is equivalent to \fBxxhsum \-H0\fR
.
.br
\fBxxh64sum\fR is equivalent to \fBxxhsum \-H1\fR
.
.br
\fBxxh128sum\fR is equivalent to \fBxxhsum \-H2\fR
\fBxxh32sum\fR is equivalent to \fBxxhsum \-H0\fR, \fBxxh64sum\fR is equivalent to \fBxxhsum \-H1\fR, \fBxxh128sum\fR is equivalent to \fBxxhsum \-H2\fR, \fBxxh3sum\fR is equivalent to \fBxxhsum \-H3\fR\.
.
.SH "DESCRIPTION"
Print or check xxHash (32, 64 or 128 bits) checksums\. When \fIFILE\fR is \fB\-\fR, read standard input\.
Print or check xxHash (32, 64 or 128 bits) checksums\. When no \fIFILE\fR, read standard input, except if it\'s the console\. When \fIFILE\fR is \fB\-\fR, read standard input even if it\'s the console\.
.
.P
\fBxxhsum\fR supports a command line syntax similar but not identical to md5sum(1)\. Differences are: \fBxxhsum\fR doesn\'t have text/binary mode switch (\fB\-b\fR, \fB\-t\fR); \fBxxhsum\fR always treats files as binary files; \fBxxhsum\fR has a hash bit width switch (\fB\-H\fR);
\fBxxhsum\fR supports a command line syntax similar but not identical to md5sum(1)\. Differences are:
.
.IP "\(bu" 4
\fBxxhsum\fR doesn\'t have text mode switch (\fB\-t\fR)
.
.IP "\(bu" 4
\fBxxhsum\fR doesn\'t have short binary mode switch (\fB\-b\fR)
.
.IP "\(bu" 4
\fBxxhsum\fR always treats files as binary file
.
.IP "\(bu" 4
\fBxxhsum\fR has a hash selection switch (\fB\-H\fR)
.
.IP "" 0
.
.P
As xxHash is a fast non\-cryptographic checksum algorithm, \fBxxhsum\fR should not be used for security related purposes\.
.
.P
\fBxxhsum \-b\fR invokes benchmark mode\. See \fIOPTIONS\fR and \fIEXAMPLES\fR for details\.
\fBxxhsum \-b\fR invokes benchmark mode\. See OPTIONS and EXAMPLES for details\.
.
.SH "OPTIONS"
.
@@ -39,11 +44,15 @@ Displays xxhsum version and exits
.
.TP
\fB\-H\fR\fIHASHTYPE\fR
Hash selection\. \fIHASHTYPE\fR means \fB0\fR=32bits, \fB1\fR=64bits, \fB2\fR=128bits\. Default value is \fB1\fR (64bits)
Hash selection\. \fIHASHTYPE\fR means \fB0\fR=XXH32, \fB1\fR=XXH64, \fB2\fR=XXH128, \fB3\fR=XXH3\. Alternatively, \fIHASHTYPE\fR \fB32\fR=XXH32, \fB64\fR=XXH64, \fB128\fR=XXH128\. Default value is \fB1\fR (XXH64)
.
.TP
\fB\-q\fR, \fB\-\-quiet\fR
Remove status messages like "Loading\.\.\." written to \fBstderr\fR \.
\fB\-\-binary\fR
Read in binary mode\.
.
.TP
\fB\-\-tag\fR
Output in the BSD style\.
.
.TP
\fB\-\-little\-endian\fR
@@ -53,8 +62,7 @@ Set output hexadecimal checksum value as little endian convention\. By default,
\fB\-h\fR, \fB\-\-help\fR
Displays help and exits
.
.P
\fBThe following four options are useful only when verifying checksums (\fB\-c\fR)\fR
.SS "The following options are useful only when verifying checksums (\-c):"
.
.TP
\fB\-c\fR, \fB\-\-check\fR \fIFILE\fR
@@ -62,7 +70,7 @@ Read xxHash sums from \fIFILE\fR and check them
.
.TP
\fB\-q\fR, \fB\-\-quiet\fR
On top of removing status messages written to \fBstderr\fR, also don\'t print OK for each successfully verified file
Don\'t print OK for each successfully verified file
.
.TP
\fB\-\-strict\fR
@@ -76,12 +84,15 @@ Don\'t output anything\. Status code shows success\.
\fB\-w\fR, \fB\-\-warn\fR
Emit a warning message about each improperly formatted checksum line\.
.
.P
\fBThe following options are useful only benchmark purpose\fR
.SS "The following options are useful only benchmark purpose:"
.
.TP
\fB\-b\fR
Benchmark mode\. See \fIEXAMPLES\fR for details\.
Benchmark mode\. See EXAMPLES for details\.
.
.TP
\fB\-b#\fR
Specify ID of variant to be tested\. Multiple variants can be selected, separated by a \',\' comma\.
.
.TP
\fB\-B\fR\fIBLOCKSIZE\fR
@@ -135,16 +146,26 @@ $ xxhsum \-c xyz\.xxh32 qux\.xxh64
.IP "" 0
.
.P
Benchmark xxHash algorithm for 16384 bytes data in 10 times\. \fBxxhsum\fR benchmarks all xxHash variants and output results to standard output\.
.
.br
The first column is the algorithm, the second column is the source data size in bytes, the third column is the number of hashes generated per second (throughput), and finally, the last column translates speed in megabytes per second\.
Benchmark xxHash algorithm\. By default, \fBxxhsum\fR benchmarks xxHash main variants on a synthetic sample of 100 KB, and print results into standard output\. The first column is the algorithm, the second column is the source data size in bytes, the third column is the number of hashes generated per second (throughput), and finally the last column translates speed in megabytes per second\.
.
.IP "" 4
.
.nf
$ xxhsum \-b \-i10 \-B16384
$ xxhsum \-b
.
.fi
.
.IP "" 0
.
.P
In the following example, the sample to hash is set to 16384 bytes, the variants to be benched are selected by their IDs, and each benchmark test is repeated 10 times, for increased accuracy\.
.
.IP "" 4
.
.nf
$ xxhsum \-b1,2,3 \-i10 \-B16384
.
.fi
.
+177
View File
@@ -0,0 +1,177 @@
xxhsum(1) -- print or check xxHash non-cryptographic checksums
==============================================================
SYNOPSIS
--------
`xxhsum` [*OPTION*]... [*FILE*]...
`xxhsum -b` [*OPTION*]...
`xxh32sum` is equivalent to `xxhsum -H0`,
`xxh64sum` is equivalent to `xxhsum -H1`,
`xxh128sum` is equivalent to `xxhsum -H2`,
`xxh3sum` is equivalent to `xxhsum -H3`.
DESCRIPTION
-----------
Print or check xxHash (32, 64 or 128 bits) checksums.
When no *FILE*, read standard input, except if it's the console.
When *FILE* is `-`, read standard input even if it's the console.
`xxhsum` supports a command line syntax similar but not identical to md5sum(1). Differences are:
* `xxhsum` doesn't have text mode switch (`-t`)
* `xxhsum` doesn't have short binary mode switch (`-b`)
* `xxhsum` always treats files as binary file
* `xxhsum` has a hash selection switch (`-H`)
As xxHash is a fast non-cryptographic checksum algorithm,
`xxhsum` should not be used for security related purposes.
`xxhsum -b` invokes benchmark mode. See OPTIONS and EXAMPLES for details.
OPTIONS
-------
* `-H`*HASHTYPE*:
Hash selection. *HASHTYPE* means `0`=XXH32, `1`=XXH64, `2`=XXH128, `3`=XXH3.
Alternatively, *HASHTYPE* `32`=XXH32, `64`=XXH64, `128`=XXH128.
Default value is `1` (XXH64)
* `--binary`:
Read in binary mode.
* `--tag`:
Output in the BSD style.
* `--little-endian`:
Set output hexadecimal checksum value as little endian convention.
By default, value is displayed as big endian.
* `-V`, `--version`:
Displays xxhsum version and exits
* `-h`, `--help`:
Displays help and exits
### Advanced file input options
* `--files-from`, `--filelist` *FILE*:
Read filenames from *FILE* and generate hashes for them.
`stdin` is also a valid way to provide filenames (when no *FILE* or `-` provided).
Valid format is one filename per line, which can include embedded spaces, etc with no need for quotes, escapes, etc.
A line commencing with '\\' will enable the convention used in the encoding of filenames against output hashes,
whereby subsequent \\\\, \n and \r seqeuences are converted to the single
character 0x5C, 0x0A and 0x0D respectively.
### The following options are useful only for checksum verification:
* `-c`, `--check` *FILE*:
Read xxHash sums from *FILE* and check them
* `--strict`:
Return an error code if any line in *FILE* is invalid,
not just if some checksums are wrong.
This policy is disabled by default,
though UI will prompt an informational message
if any line in the file is detected invalid.
* `-w`, `--warn`:
Emit a warning message about each improperly formatted line in *FILE*.
* `-q`, `--quiet`:
Don't print OK for each successfully verified hash
* `--status`:
Don't output anything. Only generate a Status code to show success.
### The following options are useful only benchmark purpose:
* `-b`:
Benchmark mode. See EXAMPLES for details.
* `-b#`:
Specify ID of variant to be tested.
Multiple variants can be selected, separated by a ',' comma.
* `-B`*BLOCKSIZE*:
Only useful for benchmark mode (`-b`). See *EXAMPLES* for details.
<BLOCKSIZE> specifies benchmark mode's test data block size in bytes.
Default value is 102400
* `-i`*ITERATIONS*:
Only useful for benchmark mode (`-b`). See *EXAMPLES* for details.
<ITERATIONS> specifies number of iterations in benchmark. Single iteration
lasts approximately 1000 milliseconds. Default value is 3
EXIT STATUS
-----------
`xxhsum` exit `0` on success, `1` if at least one file couldn't be read or
doesn't have the same checksum as the `-c` option.
EXAMPLES
--------
Output xxHash (64bit) checksum values of specific files to standard output
$ xxhsum -H1 foo bar baz
Output xxHash (32bit and 64bit) checksum values of specific files to standard
output, and redirect it to `xyz.xxh32` and `qux.xxh64`
$ xxhsum -H0 foo bar baz > xyz.xxh32
$ xxhsum -H1 foo bar baz > qux.xxh64
Read xxHash sums from specific files and check them
$ xxhsum -c xyz.xxh32 qux.xxh64
Produce a list of files, then generate hashes for that list
$ find . -type f -name '*.[ch]' > c-files.txt
$ xxhsum --files-from c-files.txt
Read the list of files from standard input to avoid the need for an intermediate file
$ find . -type f -name '*.[ch]' | xxhsum --files-from -
Note that if shell expansion, length of argument list, clarity of use of spaces in filenames, etc allow it then the same output as the previous example can be generated like this
$ xxhsum `find . -name '*.[ch]'`
Benchmark xxHash algorithm.
By default, `xxhsum` benchmarks xxHash main variants
on a synthetic sample of 100 KB,
and print results into standard output.
The first column is the algorithm,
the second column is the source data size in bytes,
the third column is the number of hashes generated per second (throughput),
and finally the last column translates speed in megabytes per second.
$ xxhsum -b
In the following example,
the sample to hash is set to 16384 bytes,
the variants to be benched are selected by their IDs,
and each benchmark test is repeated 10 times, for increased accuracy.
$ xxhsum -b1,2,3 -i10 -B16384
BUGS
----
Report bugs at: https://github.com/Cyan4973/xxHash/issues/
AUTHOR
------
Yann Collet
SEE ALSO
--------
md5sum(1)
File diff suppressed because it is too large. Load diff
+12
View File
@@ -0,0 +1,12 @@
{
"name": "xxhash",
"version": "0.8.2",
"repo": "Cyan4973/xxhash",
"description": "Extremely fast non-cryptographic hash algorithm",
"keywords": ["xxhash", "hashing"],
"license": "BSD-2-Clause",
"src": [
"xxhash.c",
"xxhash.h"
]
}
@@ -5,7 +5,7 @@
#
# For details, see <https://creativecommons.org/publicdomain/zero/1.0/>.
cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR)
cmake_minimum_required (VERSION 3.10 FATAL_ERROR)
set(XXHASH_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
@@ -25,14 +25,10 @@ if("${CMAKE_VERSION}" VERSION_LESS "3.13")
else()
cmake_policy (SET CMP0077 NEW)
endif()
if("${CMAKE_VERSION}" VERSION_LESS "3.0")
project(xxHash C)
else()
cmake_policy (SET CMP0048 NEW)
project(xxHash
VERSION ${XXHASH_VERSION_STRING}
LANGUAGES C)
endif()
cmake_policy (SET CMP0048 NEW)
project(xxHash
VERSION ${XXHASH_VERSION_STRING}
LANGUAGES C)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Project build type" FORCE)
@@ -43,8 +39,17 @@ if(NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "xxHash build type: ${CMAKE_BUILD_TYPE}")
endif()
# Enable assert() statements in debug builds
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
if("${CMAKE_VERSION}" VERSION_LESS "3.12")
# add_compile_definitions is not available for older cmake => do nothing
else()
add_compile_definitions(XXH_DEBUGLEVEL=1)
endif()
endif()
option(BUILD_SHARED_LIBS "Build shared library" ON)
set(XXHASH_BUILD_XXHSUM ON CACHE BOOL "Build the xxhsum binary")
option(XXHASH_BUILD_XXHSUM "Build the xxhsum binary" ON)
# If XXHASH is being bundled in another project, we don't want to
# install anything. However, we want to let people override this, so
@@ -66,8 +71,26 @@ mark_as_advanced(XXHASH_BUNDLED_MODE)
include(CMakeDependentOption)
CMAKE_DEPENDENT_OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON "NOT XXHASH_BUNDLED_MODE" OFF)
# detect architecture for DISPATCH mode
CMAKE_HOST_SYSTEM_INFORMATION(RESULT PLATFORM QUERY OS_PLATFORM)
message(STATUS "Architecture: ${PLATFORM}")
# libxxhash
add_library(xxhash "${XXHASH_DIR}/xxhash.c")
if((DEFINED DISPATCH) AND (DEFINED PLATFORM))
# Only support DISPATCH option on x86_64.
if(("${PLATFORM}" STREQUAL "x86_64") OR ("${PLATFORM}" STREQUAL "AMD64"))
set(XXHSUM_DISPATCH ON)
message(STATUS "Enable xxHash dispatch mode")
add_library(xxhash "${XXHASH_DIR}/xxh_x86dispatch.c"
"${XXHASH_DIR}/xxhash.c"
)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DXXHSUM_DISPATCH=1")
else()
add_library(xxhash "${XXHASH_DIR}/xxhash.c")
endif()
else()
add_library(xxhash "${XXHASH_DIR}/xxhash.c")
endif()
add_library(${PROJECT_NAME}::xxhash ALIAS xxhash)
target_include_directories(xxhash
@@ -78,12 +101,24 @@ if (BUILD_SHARED_LIBS)
target_compile_definitions(xxhash PUBLIC XXH_EXPORT)
endif ()
set_target_properties(xxhash PROPERTIES
SOVERSION "${XXHASH_VERSION_STRING}"
SOVERSION "${XXHASH_LIB_SOVERSION}"
VERSION "${XXHASH_VERSION_STRING}")
if(XXHASH_BUILD_XXHSUM)
set(XXHSUM_DIR "${XXHASH_DIR}/cli")
# xxhsum
add_executable(xxhsum "${XXHASH_DIR}/xxhsum.c")
set(XXHSUM_SOURCES)
if (XXHSUM_DISPATCH)
list(APPEND XXHSUM_SOURCES "${XXHASH_DIR}/xxh_x86dispatch.c")
endif()
list(APPEND XXHSUM_SOURCES "${XXHSUM_DIR}/xxhsum.c"
"${XXHSUM_DIR}/xsum_arch.c"
"${XXHSUM_DIR}/xsum_os_specific.c"
"${XXHSUM_DIR}/xsum_output.c"
"${XXHSUM_DIR}/xsum_sanity_check.c"
"${XXHSUM_DIR}/xsum_bench.c"
)
add_executable(xxhsum ${XXHSUM_SOURCES})
add_executable(${PROJECT_NAME}::xxhsum ALIAS xxhsum)
target_link_libraries(xxhsum PRIVATE xxhash)
@@ -95,40 +130,28 @@ include (CheckCCompilerFlag)
if (XXHASH_C_FLAGS)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${XXHASH_C_FLAGS}")
endif()
foreach (flag
-Wall -Wextra -Wcast-qual -Wcast-align -Wshadow
-Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement
-Wstrict-prototypes -Wundef)
# Because https://gcc.gnu.org/wiki/FAQ#wnowarning
string(REGEX REPLACE "\\-Wno\\-(.+)" "-W\\1" flag_to_test "${flag}")
string(REGEX REPLACE "[^a-zA-Z0-9]+" "_" test_name "CFLAG_${flag_to_test}")
check_c_compiler_flag("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${test_name})
if(${test_name})
set(CMAKE_C_FLAGS "${flag} ${CMAKE_C_FLAGS}")
endif()
unset(test_name)
unset(flag_to_test)
endforeach (flag)
if(NOT XXHASH_BUNDLED_MODE)
include(GNUInstallDirs)
install(TARGETS xxhash
EXPORT xxHashTargets
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
install(FILES "${XXHASH_DIR}/xxhash.h"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(FILES "${XXHASH_DIR}/xxh3.h"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
if(DISPATCH)
install(FILES "${XXHASH_DIR}/xxh_x86dispatch.h"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
endif()
if(XXHASH_BUILD_XXHSUM)
install(TARGETS xxhsum
EXPORT xxHashTargets
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
install(FILES "${XXHASH_DIR}/xxhsum.1"
install(FILES "${XXHSUM_DIR}/xxhsum.1"
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1")
endif(XXHASH_BUILD_XXHSUM)
@@ -145,23 +168,28 @@ if(NOT XXHASH_BUNDLED_MODE)
${PROJECT_SOURCE_DIR}/xxHashConfig.cmake.in
${xxHash_PROJECT_CONFIG}
INSTALL_DESTINATION ${xxHash_CONFIG_INSTALL_DIR})
if("${CMAKE_VERSION}" VERSION_LESS "3.0")
set(XXHASH_EXPORT_SET xxhash)
if(XXHASH_BUILD_XXHSUM)
set(XXHASH_EXPORT_SET ${XXHASH_EXPORT_SET} xxhsum)
endif()
export(TARGETS ${XXHASH_EXPORT_SET}
FILE ${xxHash_TARGETS_CONFIG}
NAMESPACE ${PROJECT_NAME}::)
else()
export(EXPORT xxHashTargets
FILE ${xxHash_TARGETS_CONFIG}
NAMESPACE ${PROJECT_NAME}::)
endif()
install(FILES ${xxHash_PROJECT_CONFIG} ${xxHash_VERSION_CONFIG}
DESTINATION ${xxHash_CONFIG_INSTALL_DIR})
install(EXPORT xxHashTargets
DESTINATION ${xxHash_CONFIG_INSTALL_DIR}
NAMESPACE ${PROJECT_NAME}::)
# configure and install pkg-config
include(JoinPaths.cmake)
set(PREFIX ${CMAKE_INSTALL_PREFIX})
set(EXECPREFIX "\${prefix}")
join_paths(INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
join_paths(LIBDIR "\${prefix}" "${CMAKE_INSTALL_LIBDIR}")
set(VERSION "${XXHASH_VERSION_STRING}")
configure_file(${XXHASH_DIR}/libxxhash.pc.in ${CMAKE_BINARY_DIR}/libxxhash.pc @ONLY)
install(FILES ${CMAKE_BINARY_DIR}/libxxhash.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif(NOT XXHASH_BUNDLED_MODE)
include(CPack)
@@ -0,0 +1,23 @@
# This module provides function for joining paths
# known from most languages
#
# SPDX-License-Identifier: (MIT OR CC0-1.0)
# Copyright 2020 Jan Tojnar
# https://github.com/jtojnar/cmake-snips
#
# Modelled after Python’s os.path.join
# https://docs.python.org/3.7/library/os.path.html#os.path.join
# Windows not supported
function(join_paths joined_path first_path_segment)
set(temp_path "${first_path_segment}")
foreach(current_segment IN LISTS ARGN)
if(NOT ("${current_segment}" STREQUAL ""))
if(IS_ABSOLUTE "${current_segment}")
set(temp_path "${current_segment}")
else()
set(temp_path "${temp_path}/${current_segment}")
endif()
endif()
endforeach()
set(${joined_path} "${temp_path}" PARENT_SCOPE)
endfunction()
+2 -1
View File
@@ -16,6 +16,7 @@ Where possible options are:
- `-DXXHASH_BUILD_XXHSUM=<ON|OFF>`: build the command line binary. ON by default
- `-DBUILD_SHARED_LIBS=<ON|OFF>`: build dynamic library. ON by default.
- `-DCMAKE_INSTALL_PREFIX=<path>`: use custom install prefix path.
- `-DDISPATCH=<ON|OFF>`: enable dispatch mode. OFF by default.
Add lines into downstream CMakeLists.txt:
@@ -26,7 +27,7 @@ Add lines into downstream CMakeLists.txt:
### Way 2: Add subdirectory
Add lines into downstream CMakeLists.txt:
option(BUILD_SHARE_LIBS "Build shared libs" OFF) #optional
option(BUILD_SHARED_LIBS "Build shared libs" OFF) #optional
...
set(XXHASH_BUILD_ENABLE_INLINE_API OFF) #optional
set(XXHASH_BUILD_XXHSUM OFF) #optional
+206
View File
@@ -0,0 +1,206 @@
module xxhash where
/**
* The 32-bit variant of xxHash. The first argument is the sequence
* of L bytes to hash. The second argument is a seed value.
*/
XXH32 : {L} (fin L) => [L][8] -> [32] -> [32]
XXH32 input seed = XXH32_avalanche acc1
where (stripes16 # stripes4 # stripes1) = input
accR = foldl XXH32_rounds (XXH32_init seed) (split stripes16 : [L/16][16][8])
accL = `(L % 2^^32) + if (`L:Integer) < 16
then seed + PRIME32_5
else XXH32_converge accR
acc4 = foldl XXH32_digest4 accL (split stripes4 : [(L%16)/4][4][8])
acc1 = foldl XXH32_digest1 acc4 (stripes1 : [L%4][8])
/**
* The 64-bit variant of xxHash. The first argument is the sequence
* of L bytes to hash. The second argument is a seed value.
*/
XXH64 : {L} (fin L) => [L][8] -> [64] -> [64]
XXH64 input seed = XXH64_avalanche acc1
where (stripes32 # stripes8 # stripes4 # stripes1) = input
accR = foldl XXH64_rounds (XXH64_init seed) (split stripes32 : [L/32][32][8])
accL = `(L % 2^^64) + if (`L:Integer) < 32
then seed + PRIME64_5
else XXH64_converge accR
acc8 = foldl XXH64_digest8 accL (split stripes8 : [(L%32)/8][8][8])
acc4 = foldl XXH64_digest4 acc8 (split stripes4 : [(L%8)/4][4][8])
acc1 = foldl XXH64_digest1 acc4 (stripes1 : [L%4][8])
private
//Utility functions
/**
* Combines a sequence of bytes into a word using the little-endian
* convention.
*/
toLE bytes = join (reverse bytes)
//32-bit xxHash helper functions
//32-bit prime number constants
PRIME32_1 = 0x9E3779B1 : [32]
PRIME32_2 = 0x85EBCA77 : [32]
PRIME32_3 = 0xC2B2AE3D : [32]
PRIME32_4 = 0x27D4EB2F : [32]
PRIME32_5 = 0x165667B1 : [32]
/**
* The property shows that the hexadecimal representation of the
* PRIME32 constants is the same as the binary representation.
*/
property PRIME32s_as_bits_correct =
(PRIME32_1 == 0b10011110001101110111100110110001) /\
(PRIME32_2 == 0b10000101111010111100101001110111) /\
(PRIME32_3 == 0b11000010101100101010111000111101) /\
(PRIME32_4 == 0b00100111110101001110101100101111) /\
(PRIME32_5 == 0b00010110010101100110011110110001)
/**
* This function initializes the four internal accumulators of XXH32.
*/
XXH32_init : [32] -> [4][32]
XXH32_init seed = [acc1, acc2, acc3, acc4]
where acc1 = seed + PRIME32_1 + PRIME32_2
acc2 = seed + PRIME32_2
acc3 = seed + 0
acc4 = seed - PRIME32_1
/**
* This processes a single lane of the main round function of XXH32.
*/
XXH32_round : [32] -> [32] -> [32]
XXH32_round accN laneN = ((accN + laneN * PRIME32_2) <<< 13) * PRIME32_1
/**
* This is the main round function of XXH32 and processes a stripe,
* i.e. 4 lanes with 4 bytes each.
*/
XXH32_rounds : [4][32] -> [16][8] -> [4][32]
XXH32_rounds accs stripe =
[ XXH32_round accN (toLE laneN) | accN <- accs | laneN <- split stripe ]
/**
* This function combines the four lane accumulators into a single
* 32-bit value.
*/
XXH32_converge : [4][32] -> [32]
XXH32_converge [acc1, acc2, acc3, acc4] =
(acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18)
/**
* This function digests a four byte lane
*/
XXH32_digest4 : [32] -> [4][8] -> [32]
XXH32_digest4 acc lane = ((acc + toLE lane * PRIME32_3) <<< 17) * PRIME32_4
/**
* This function digests a single byte lane
*/
XXH32_digest1 : [32] -> [8] -> [32]
XXH32_digest1 acc lane = ((acc + (0 # lane) * PRIME32_5) <<< 11) * PRIME32_1
/**
* This function ensures that all input bits have a chance to impact
* any bit in the output digest, resulting in an unbiased
* distribution.
*/
XXH32_avalanche : [32] -> [32]
XXH32_avalanche acc0 = acc5
where acc1 = acc0 ^ (acc0 >> 15)
acc2 = acc1 * PRIME32_2
acc3 = acc2 ^ (acc2 >> 13)
acc4 = acc3 * PRIME32_3
acc5 = acc4 ^ (acc4 >> 16)
//64-bit xxHash helper functions
//64-bit prime number constants
PRIME64_1 = 0x9E3779B185EBCA87 : [64]
PRIME64_2 = 0xC2B2AE3D27D4EB4F : [64]
PRIME64_3 = 0x165667B19E3779F9 : [64]
PRIME64_4 = 0x85EBCA77C2B2AE63 : [64]
PRIME64_5 = 0x27D4EB2F165667C5 : [64]
/**
* The property shows that the hexadecimal representation of the
* PRIME64 constants is the same as the binary representation.
*/
property PRIME64s_as_bits_correct =
(PRIME64_1 == 0b1001111000110111011110011011000110000101111010111100101010000111) /\
(PRIME64_2 == 0b1100001010110010101011100011110100100111110101001110101101001111) /\
(PRIME64_3 == 0b0001011001010110011001111011000110011110001101110111100111111001) /\
(PRIME64_4 == 0b1000010111101011110010100111011111000010101100101010111001100011) /\
(PRIME64_5 == 0b0010011111010100111010110010111100010110010101100110011111000101)
/**
* This function initializes the four internal accumulators of XXH64.
*/
XXH64_init : [64] -> [4][64]
XXH64_init seed = [acc1, acc2, acc3, acc4]
where acc1 = seed + PRIME64_1 + PRIME64_2
acc2 = seed + PRIME64_2
acc3 = seed + 0
acc4 = seed - PRIME64_1
/**
* This processes a single lane of the main round function of XXH64.
*/
XXH64_round : [64] -> [64] -> [64]
XXH64_round accN laneN = ((accN + laneN * PRIME64_2) <<< 31) * PRIME64_1
/**
* This is the main round function of XXH64 and processes a stripe,
* i.e. 4 lanes with 8 bytes each.
*/
XXH64_rounds : [4][64] -> [32][8] -> [4][64]
XXH64_rounds accs stripe =
[ XXH64_round accN (toLE laneN) | accN <- accs | laneN <- split stripe ]
/**
* This is a helper function, used to merge the four lane accumulators.
*/
mergeAccumulator : [64] -> [64] -> [64]
mergeAccumulator acc accN = (acc ^ XXH64_round 0 accN) * PRIME64_1 + PRIME64_4
/**
* This function combines the four lane accumulators into a single
* 64-bit value.
*/
XXH64_converge : [4][64] -> [64]
XXH64_converge [acc1, acc2, acc3, acc4] =
foldl mergeAccumulator ((acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18)) [acc1, acc2, acc3, acc4]
/**
* This function digests an eight byte lane
*/
XXH64_digest8 : [64] -> [8][8] -> [64]
XXH64_digest8 acc lane = ((acc ^ XXH64_round 0 (toLE lane)) <<< 27) * PRIME64_1 + PRIME64_4
/**
* This function digests a four byte lane
*/
XXH64_digest4 : [64] -> [4][8] -> [64]
XXH64_digest4 acc lane = ((acc ^ (0 # toLE lane) * PRIME64_1) <<< 23) * PRIME64_2 + PRIME64_3
/**
* This function digests a single byte lane
*/
XXH64_digest1 : [64] -> [8] -> [64]
XXH64_digest1 acc lane = ((acc ^ (0 # lane) * PRIME64_5) <<< 11) * PRIME64_1
/**
* This function ensures that all input bits have a chance to impact
* any bit in the output digest, resulting in an unbiased
* distribution.
*/
XXH64_avalanche : [64] -> [64]
XXH64_avalanche acc0 = acc5
where acc1 = acc0 ^ (acc0 >> 33)
acc2 = acc1 * PRIME64_2
acc3 = acc2 ^ (acc2 >> 29)
acc4 = acc3 * PRIME64_3
acc5 = acc4 ^ (acc4 >> 32)
+588 -85
View File
@@ -16,7 +16,7 @@ Distribution of this document is unlimited.
### Version
0.1.1 (10/10/18)
0.2.0 (29/06/23)
Table of Contents
@@ -24,6 +24,10 @@ Table of Contents
- [Introduction](#introduction)
- [XXH32 algorithm description](#xxh32-algorithm-description)
- [XXH64 algorithm description](#xxh64-algorithm-description)
- [XXH3 algorithm description](#xxh3-algorithm-overview)
- [Small inputs](#xxh3-algorithm-description-for-small-inputs)
- [Medium inputs](#xxh3-algorithm-description-for-medium-inputs)
- [Large inputs](#xxh3-algorithm-description-for-large-inputs)
- [Performance considerations](#performance-considerations)
- [Reference Implementation](#reference-implementation)
@@ -43,13 +47,20 @@ However, a given variant shall produce exactly the same output, irrespective of
### Operation notations
All operations are performed modulo {32,64} bits. Arithmetic overflows are expected.
`XXH32` uses 32-bit modular operations. `XXH64` uses 64-bit modular operations.
`XXH32` uses 32-bit modular operations.
`XXH64` and `XXH3` use 64-bit modular operations.
When an operation ingests input or secret as multi-bytes values, it reads it using little-endian convention.
- `+`: denotes modular addition
- `-`: denotes modular subtraction
- `*`: denotes modular multiplication
- **Exception:** In `XXH3`, if it is in the form `(u128)x * (u128)y`, it denotes 64-bit by 64-bit normal multiplication into a full 128-bit result.
- `X <<< s`: denotes the value obtained by circularly shifting (rotating) `X` left by `s` bit positions.
- `X >> s`: denotes the value obtained by shifting `X` right by s bit positions. Upper `s` bits become `0`.
- `X << s`: denotes the value obtained by shifting `X` left by s bit positions. Lower `s` bits become `0`.
- `X xor Y`: denotes the bit-wise XOR of `X` and `Y` (same width).
- `X | Y`: denotes the bit-wise OR of `X` and `Y` (same width).
- `~X`: denotes the bit-wise negation of `X`.
XXH32 Algorithm Description
@@ -63,11 +74,13 @@ The algorithm collect and transform input in _stripes_ of 16 bytes. The transfor
The algorithm uses 32-bits addition, multiplication, rotate, shift and xor operations. Many operations require some 32-bits prime number constants, all defined below:
static const u32 PRIME32_1 = 0x9E3779B1U; // 0b10011110001101110111100110110001
static const u32 PRIME32_2 = 0x85EBCA77U; // 0b10000101111010111100101001110111
static const u32 PRIME32_3 = 0xC2B2AE3DU; // 0b11000010101100101010111000111101
static const u32 PRIME32_4 = 0x27D4EB2FU; // 0b00100111110101001110101100101111
static const u32 PRIME32_5 = 0x165667B1U; // 0b00010110010101100110011110110001
```c
static const u32 PRIME32_1 = 0x9E3779B1U; // 0b10011110001101110111100110110001
static const u32 PRIME32_2 = 0x85EBCA77U; // 0b10000101111010111100101001110111
static const u32 PRIME32_3 = 0xC2B2AE3DU; // 0b11000010101100101010111000111101
static const u32 PRIME32_4 = 0x27D4EB2FU; // 0b00100111110101001110101100101111
static const u32 PRIME32_5 = 0x165667B1U; // 0b00010110010101100110011110110001
```
These constants are prime numbers, and feature a good mix of bits 1 and 0, neither too regular, nor too dissymmetric. These properties help dispersion capabilities.
@@ -75,10 +88,12 @@ These constants are prime numbers, and feature a good mix of bits 1 and 0, neith
Each accumulator gets an initial value based on optional `seed` input. Since the `seed` is optional, it can be `0`.
u32 acc1 = seed + PRIME32_1 + PRIME32_2;
u32 acc2 = seed + PRIME32_2;
u32 acc3 = seed + 0;
u32 acc4 = seed - PRIME32_1;
```c
u32 acc1 = seed + PRIME32_1 + PRIME32_2;
u32 acc2 = seed + PRIME32_2;
u32 acc3 = seed + 0;
u32 acc4 = seed - PRIME32_1;
```
#### Special case: input is less than 16 bytes
@@ -86,7 +101,9 @@ When the input is too small (< 16 bytes), the algorithm will not process any str
In this case, a simplified initialization is performed, using a single accumulator:
u32 acc = seed + PRIME32_5;
```c
u32 acc = seed + PRIME32_5;
```
The algorithm then proceeds directly to step 4.
@@ -100,9 +117,11 @@ Each lane read its associated 32-bit value using __little-endian__ convention.
For each {lane, accumulator}, the update process is called a _round_, and applies the following formula:
accN = accN + (laneN * PRIME32_2);
accN = accN <<< 13;
accN = accN * PRIME32_1;
```c
accN = accN + (laneN * PRIME32_2);
accN = accN <<< 13;
accN = accN * PRIME32_1;
```
This shuffles the bits so that any bit from input _lane_ impacts several bits in output _accumulator_. All operations are performed modulo 2^32.
@@ -113,13 +132,17 @@ When that happens, move to step 3.
All 4 lane accumulators from the previous steps are merged to produce a single remaining accumulator of the same width (32-bit). The associated formula is as follows:
acc = (acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18);
```c
acc = (acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18);
```
### Step 4. Add input length
The input total length is presumed known at this stage. This step is just about adding the length to accumulator, so that it participates to final mixing.
acc = acc + (u32)inputLength;
```c
acc = acc + (u32)inputLength;
```
Note that, if input length is so large that it requires more than 32-bits, only the lower 32-bits are added to the accumulator.
@@ -128,19 +151,21 @@ Note that, if input length is so large that it requires more than 32-bits, only
There may be up to 15 bytes remaining to consume from the input.
The final stage will digest them according to following pseudo-code:
while (remainingLength >= 4) {
lane = read_32bit_little_endian(input_ptr);
acc = acc + lane * PRIME32_3;
acc = (acc <<< 17) * PRIME32_4;
input_ptr += 4; remainingLength -= 4;
}
```c
while (remainingLength >= 4) {
lane = read_32bit_little_endian(input_ptr);
acc = acc + lane * PRIME32_3;
acc = (acc <<< 17) * PRIME32_4;
input_ptr += 4; remainingLength -= 4;
}
while (remainingLength >= 1) {
lane = read_byte(input_ptr);
acc = acc + lane * PRIME32_5;
acc = (acc <<< 11) * PRIME32_1;
input_ptr += 1; remainingLength -= 1;
}
while (remainingLength >= 1) {
lane = read_byte(input_ptr);
acc = acc + lane * PRIME32_5;
acc = (acc <<< 11) * PRIME32_1;
input_ptr += 1; remainingLength -= 1;
}
```
This process ensures that all input bytes are present in the final mix.
@@ -148,11 +173,13 @@ This process ensures that all input bytes are present in the final mix.
The final mix ensures that all input bits have a chance to impact any bit in the output digest, resulting in an unbiased distribution. This is also called avalanche effect.
acc = acc xor (acc >> 15);
acc = acc * PRIME32_2;
acc = acc xor (acc >> 13);
acc = acc * PRIME32_3;
acc = acc xor (acc >> 16);
```c
acc = acc xor (acc >> 15);
acc = acc * PRIME32_2;
acc = acc xor (acc >> 13);
acc = acc * PRIME32_3;
acc = acc xor (acc >> 16);
```
### Step 7. Output
@@ -172,22 +199,26 @@ The algorithm collects and transforms input in _stripes_ of 32 bytes. The transf
The algorithm uses 64-bit addition, multiplication, rotate, shift and xor operations. Many operations require some 64-bit prime number constants, all defined below:
static const u64 PRIME64_1 = 0x9E3779B185EBCA87ULL; // 0b1001111000110111011110011011000110000101111010111100101010000111
static const u64 PRIME64_2 = 0xC2B2AE3D27D4EB4FULL; // 0b1100001010110010101011100011110100100111110101001110101101001111
static const u64 PRIME64_3 = 0x165667B19E3779F9ULL; // 0b0001011001010110011001111011000110011110001101110111100111111001
static const u64 PRIME64_4 = 0x85EBCA77C2B2AE63ULL; // 0b1000010111101011110010100111011111000010101100101010111001100011
static const u64 PRIME64_5 = 0x27D4EB2F165667C5ULL; // 0b0010011111010100111010110010111100010110010101100110011111000101
```c
static const u64 PRIME64_1 = 0x9E3779B185EBCA87ULL; // 0b1001111000110111011110011011000110000101111010111100101010000111
static const u64 PRIME64_2 = 0xC2B2AE3D27D4EB4FULL; // 0b1100001010110010101011100011110100100111110101001110101101001111
static const u64 PRIME64_3 = 0x165667B19E3779F9ULL; // 0b0001011001010110011001111011000110011110001101110111100111111001
static const u64 PRIME64_4 = 0x85EBCA77C2B2AE63ULL; // 0b1000010111101011110010100111011111000010101100101010111001100011
static const u64 PRIME64_5 = 0x27D4EB2F165667C5ULL; // 0b0010011111010100111010110010111100010110010101100110011111000101
```
These constants are prime numbers, and feature a good mix of bits 1 and 0, neither too regular, nor too dissymmetric. These properties help dispersion capabilities.
### Step 1. Initialise internal accumulators
### Step 1. Initialize internal accumulators
Each accumulator gets an initial value based on optional `seed` input. Since the `seed` is optional, it can be `0`.
u64 acc1 = seed + PRIME64_1 + PRIME64_2;
u64 acc2 = seed + PRIME64_2;
u64 acc3 = seed + 0;
u64 acc4 = seed - PRIME64_1;
```c
u64 acc1 = seed + PRIME64_1 + PRIME64_2;
u64 acc2 = seed + PRIME64_2;
u64 acc3 = seed + 0;
u64 acc4 = seed - PRIME64_1;
```
#### Special case: input is less than 32 bytes
@@ -195,7 +226,9 @@ When the input is too small (< 32 bytes), the algorithm will not process any str
In this case, a simplified initialization is performed, using a single accumulator:
u64 acc = seed + PRIME64_5;
```c
u64 acc = seed + PRIME64_5;
```
The algorithm then proceeds directly to step 4.
@@ -209,10 +242,12 @@ Each lane read its associated 64-bit value using __little-endian__ convention.
For each {lane, accumulator}, the update process is called a _round_, and applies the following formula:
round(accN,laneN):
accN = accN + (laneN * PRIME64_2);
accN = accN <<< 31;
return accN * PRIME64_1;
```c
round(accN,laneN):
accN = accN + (laneN * PRIME64_2);
accN = accN <<< 31;
return accN * PRIME64_1;
```
This shuffles the bits so that any bit from input _lane_ impacts several bits in output _accumulator_. All operations are performed modulo 2^64.
@@ -225,52 +260,60 @@ All 4 lane accumulators from previous steps are merged to produce a single remai
Note that accumulator convergence is more complex than 32-bit variant, and requires to define another function called _mergeAccumulator()_:
mergeAccumulator(acc,accN):
acc = acc xor round(0, accN);
acc = acc * PRIME64_1
return acc + PRIME64_4;
```c
mergeAccumulator(acc,accN):
acc = acc xor round(0, accN);
acc = acc * PRIME64_1;
return acc + PRIME64_4;
```
which is then used in the convergence formula:
acc = (acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18);
acc = mergeAccumulator(acc, acc1);
acc = mergeAccumulator(acc, acc2);
acc = mergeAccumulator(acc, acc3);
acc = mergeAccumulator(acc, acc4);
```c
acc = (acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18);
acc = mergeAccumulator(acc, acc1);
acc = mergeAccumulator(acc, acc2);
acc = mergeAccumulator(acc, acc3);
acc = mergeAccumulator(acc, acc4);
```
### Step 4. Add input length
The input total length is presumed known at this stage. This step is just about adding the length to accumulator, so that it participates to final mixing.
acc = acc + inputLength;
```c
acc = acc + inputLength;
```
### Step 5. Consume remaining input
There may be up to 31 bytes remaining to consume from the input.
The final stage will digest them according to following pseudo-code:
while (remainingLength >= 8) {
lane = read_64bit_little_endian(input_ptr);
acc = acc xor round(0, lane);
acc = (acc <<< 27) * PRIME64_1;
acc = acc + PRIME64_4;
input_ptr += 8; remainingLength -= 8;
}
```c
while (remainingLength >= 8) {
lane = read_64bit_little_endian(input_ptr);
acc = acc xor round(0, lane);
acc = (acc <<< 27) * PRIME64_1;
acc = acc + PRIME64_4;
input_ptr += 8; remainingLength -= 8;
}
if (remainingLength >= 4) {
lane = read_32bit_little_endian(input_ptr);
acc = acc xor (lane * PRIME64_1);
acc = (acc <<< 23) * PRIME64_2;
acc = acc + PRIME64_3;
input_ptr += 4; remainingLength -= 4;
}
if (remainingLength >= 4) {
lane = read_32bit_little_endian(input_ptr);
acc = acc xor (lane * PRIME64_1);
acc = (acc <<< 23) * PRIME64_2;
acc = acc + PRIME64_3;
input_ptr += 4; remainingLength -= 4;
}
while (remainingLength >= 1) {
lane = read_byte(input_ptr);
acc = acc xor (lane * PRIME64_5);
acc = (acc <<< 11) * PRIME64_1;
input_ptr += 1; remainingLength -= 1;
}
while (remainingLength >= 1) {
lane = read_byte(input_ptr);
acc = acc xor (lane * PRIME64_5);
acc = (acc <<< 11) * PRIME64_1;
input_ptr += 1; remainingLength -= 1;
}
```
This process ensures that all input bytes are present in the final mix.
@@ -278,11 +321,13 @@ This process ensures that all input bytes are present in the final mix.
The final mix ensures that all input bits have a chance to impact any bit in the output digest, resulting in an unbiased distribution. This is also called avalanche effect.
acc = acc xor (acc >> 33);
acc = acc * PRIME64_2;
acc = acc xor (acc >> 29);
acc = acc * PRIME64_3;
acc = acc xor (acc >> 32);
```c
acc = acc xor (acc >> 33);
acc = acc * PRIME64_2;
acc = acc xor (acc >> 29);
acc = acc * PRIME64_3;
acc = acc xor (acc >> 32);
```
### Step 7. Output
@@ -290,6 +335,462 @@ The `XXH64()` function produces an unsigned 64-bit value as output.
For systems which require to store and/or display the result in binary or hexadecimal format, the canonical format is defined to reproduce the same value as the natural decimal format, hence follows __big-endian__ convention (most significant byte first).
XXH3 Algorithm Overview
-------------------------------------
XXH3 comes in two different versions: XXH3-64 and XXH3-128 (or XXH128), producing 64 and 128 bits of output, respectively.
XXH3 uses different algorithms for small (0-16 bytes), medium (17-240 bytes), and large (241+ bytes) inputs. The algorithms for small and medium inputs are optimized for performance. The three algorithms are described in the following sections.
Many operations require some 64-bit prime number constants, which are mostly the same constants used in XXH32 and XXH64, all defined below:
```c
static const u64 PRIME32_1 = 0x9E3779B1U; // 0b10011110001101110111100110110001
static const u64 PRIME32_2 = 0x85EBCA77U; // 0b10000101111010111100101001110111
static const u64 PRIME32_3 = 0xC2B2AE3DU; // 0b11000010101100101010111000111101
static const u64 PRIME64_1 = 0x9E3779B185EBCA87ULL; // 0b1001111000110111011110011011000110000101111010111100101010000111
static const u64 PRIME64_2 = 0xC2B2AE3D27D4EB4FULL; // 0b1100001010110010101011100011110100100111110101001110101101001111
static const u64 PRIME64_3 = 0x165667B19E3779F9ULL; // 0b0001011001010110011001111011000110011110001101110111100111111001
static const u64 PRIME64_4 = 0x85EBCA77C2B2AE63ULL; // 0b1000010111101011110010100111011111000010101100101010111001100011
static const u64 PRIME64_5 = 0x27D4EB2F165667C5ULL; // 0b0010011111010100111010110010111100010110010101100110011111000101
static const u64 PRIME_MX1 = 0x165667919E3779F9ULL; // 0b0001011001010110011001111001000110011110001101110111100111111001
static const u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; // 0b1001111110110010000111000110010100011110100110001101111100100101
```
The `XXH3_64bits()` function produces an unsigned 64-bit value.
The `XXH3_128bits()` function produces a `XXH128_hash_t` struct containing `low64` and `high64` - the lower and higher 64-bit half values of the result, respectively.
For systems requiring storing and/or displaying the result in binary or hexadecimal format, the canonical format is defined to reproduce the same value as the natural decimal format, hence following **big-endian** convention (most significant byte first).
### Seed and Secret
XXH3 provides seeded hashing by introducing two configurable constants used in the hashing process: the seed and the secret. The seed is an unsigned 64-bit value, and the secret is an array of bytes that is at least 136 bytes in size. The default seed is 0, and the default secret is the following 192-byte value:
```c
static const u8 defaultSecret[192] = {
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,
0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,
0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,
0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,
0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,
0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
};
```
The seed and the secret can be optionally specified using the `*_withSecret` and `*_withSeed` versions of the hash function.
The seed and the secret cannot be specified simultaneously (`*_withSecretAndSeed` is actually `*_withSeed` for short and medium inputs <= 240 bytes, and `*_withSecret` for large inputs). When one is specified, the other one uses the default value.
There is one exception though: when input is large (> 240 bytes) and a seed is given, a secret is derived from the seed value and the default secret using the following procedure:
```c
deriveSecret(u64 seed):
u64 derivedSecret[24] = defaultSecret[0:192];
for (i = 0; i < 12; i++) {
derivedSecret[i*2] += seed;
derivedSecret[i*2+1] -= seed;
}
return derivedSecret; // convert to u8[192] (little-endian)
```
The derivation treats the secrets as 24 64-bit values. In XXH3 algorithms, the secret is always read similarly by treating a contiguous segment of the array as one or more 32-bit or 64-bit values. **The secret values are always read using little-endian convention**.
### Final Mixing Step (avalanche)
To make sure that all input bits have a chance to impact any bit in the output digest (avalanche effect), the final step of the XXH3 algorithm is usually one of the two fixed operations that mix the bits in a 64-bit value. These operations are denoted `avalanche()` and `avalanche_XXH64()` in the following XXH3 description.
```c
avalanche(u64 x):
x = x xor (x >> 37);
x = x * PRIME_MX1;
x = x xor (x >> 32);
return x;
avalanche_XXH64(u64 x):
x = x xor (x >> 33);
x = x * PRIME64_2;
x = x xor (x >> 29);
x = x * PRIME64_3;
x = x xor (x >> 32);
return x;
```
XXH3 Algorithm Description (for small inputs)
-------------------------------------
The algorithm for small inputs (0-16 bytes of input) is further divided into 4 cases: empty, 1-3 bytes, 4-8 bytes, and 9-16 bytes of input.
The algorithm uses byte-swap operations. The byte-swap operation reverses the byte order in a 32-bit or 64-bit value. It is denoted `bswap32` and `bswap64` for its 32-bit and 64-bit versions, respectively.
### Empty input
The hash of empty input is calculated from the seed and a segment of the secret:
```c
XXH3_64_empty():
u64 secretWords[2] = secret[56:72];
return avalanche_XXH64(seed xor secretWords[0] xor secretWords[1]);
XXH3_128_empty():
u64 secretWords[4] = secret[64:96];
return {avalanche_XXH64(seed xor secretWords[0] xor secretWords[1]), // lower half
avalanche_XXH64(seed xor secretWords[2] xor secretWords[3])}; // higher half
```
### 1-3 bytes of input
The algorithm starts from a single 32-bit value combining the input bytes and its length:
```c
u32 combined = (u32)input[inputLength-1] | ((u32)inputLength << 8) |
((u32)input[0] << 16) | ((u32)input[inputLength>>1] << 24);
// LSB 8 16 24 MSB
// | last byte | length | first byte | middle-or-last byte |
```
Then the final output is calculated from the value and the first 8 bytes (XXH3-64) or 16 bytes (XXH3-128) of the secret to produce the final result. The secret here is read as 32-bit values instead of the usual 64-bit values.
```c
XXH3_64_1to3():
u32 secretWords[2] = secret[0:8];
u64 value = ((u64)(secretWords[0] xor secretWords[1]) + seed) xor (u64)combined;
return avalanche_XXH64(value);
XXH3_128_1to3():
u32 secretWords[4] = secret[0:16];
u64 low = ((u64)(secretWords[0] xor secretWords[1]) + seed) xor (u64)combined;
u64 high = ((u64)(secretWords[2] xor secretWords[3]) - seed) xor (u64)(bswap32(combined) <<< 13);
// note that the bswap32(combined) <<< 13 above is 32-bit rotate
return {avalanche_XXH64(low), // lower half
avalanche_XXH64(high)}; // higher half
```
Note that the XXH3-64 result is the lower half of XXH3-128 result.
### 4-8 bytes of input
The algorithm starts from reading the first and last 4 bytes of the input as little-endian 32-bit values, and a modified seed:
```c
u32 inputFirst = input[0:4];
u32 inputLast = input[inputLength-4:inputLength];
u64 modifiedSeed = seed xor ((u64)bswap32((u32)lowerHalf(seed)) << 32);
```
Again, these values are combined with a segment of the secret to produce the final value.
```c
XXH3_64_4to8():
u64 secretWords[2] = secret[8:24];
u64 combined = (u64)inputLast | ((u64)inputFirst << 32);
u64 value = ((secretWords[0] xor secretWords[1]) - modifiedSeed) xor combined;
value = value xor (value <<< 49) xor (value <<< 24);
value = value * PRIME_MX2;
value = value xor ((value >> 35) + inputLength);
value = value * PRIME_MX2;
value = value xor (value >> 28);
return value;
XXH3_128_4to8():
u64 secretWords[2] = secret[16:32];
u64 combined = (u64)inputFirst | ((u64)inputLast << 32);
u64 value = ((secretWords[0] xor secretWords[1]) + modifiedSeed) xor combined;
u128 mulResult = (u128)value * (u128)(PRIME64_1 + (inputLength << 2));
u64 high = higherHalf(mulResult); // mulResult >> 64
u64 low = lowerHalf(mulResult); // mulResult & 0xFFFFFFFFFFFFFFFF
high = high + (low << 1);
low = low xor (high >> 3);
low = low xor (low >> 35);
low = low * PRIME_MX2;
low = low xor (low >> 28);
high = avalanche(high);
return {low, high};
```
### 9-16 bytes of input
The algorithm starts from reading the first and last 8 bytes of the input as little-endian 64-bit values:
```c
u64 inputFirst = input[0:8];
u64 inputLast = input[inputLength-8:inputLength];
```
Once again, these values are combined with a segment of the secret to produce the final value.
```c
XXH3_64_9to16():
u64 secretWords[4] = secret[24:56];
u64 low = ((secretWords[0] xor secretWords[1]) + seed) xor inputFirst;
u64 high = ((secretWords[2] xor secretWords[3]) - seed) xor inputLast;
u128 mulResult = (u128)low * (u128)high;
u64 value = inputLength + bswap64(low) + high + (u64)(lowerHalf(mulResult) xor higherHalf(mulResult));
return avalanche(value);
XXH3_128_9to16():
u64 secretWords[4] = secret[32:64];
u64 val1 = ((secretWords[0] xor secretWords[1]) - seed) xor inputFirst xor inputLast;
u64 val2 = ((secretWords[2] xor secretWords[3]) + seed) xor inputLast;
u128 mulResult = (u128)val1 * (u128)PRIME64_1;
u64 low = lowerHalf(mulResult) + ((u64)(inputLength - 1) << 54);
u64 high = higherHalf(mulResult) + ((u64)higherHalf(val2) << 32) + (u64)lowerHalf(val2) * PRIME32_2;
// the above line can also be simplified to higherHalf(mulResult) + val2 + (u64)lowerHalf(val2) * (PRIME32_2 - 1);
low = low xor bswap64(high);
// the following three lines are in fact a 128x64 -> 128 multiplication ({low,high} = (u128){low,high} * PRIME64_2)
u128 mulResult2 = (u128)low * (u128)PRIME64_2;
low = lowerHalf(mulResult2);
high = higherHalf(mulResult2) + high * PRIME64_2;
return {avalanche(low), // lower half
avalanche(high)}; // higher half
```
XXH3 Algorithm Description (for medium inputs)
-------------------------------------
This algorithm is used for medium inputs (17-240 bytes of input). Its internal hash state is stored inside 1 (XXH3-64) or 2 (XXH3-128) "accumulators", each storing an unsigned 64-bit value.
### Step 1. Initialize internal accumulators
The accumulator(s) are initialized based on the input length.
```c
// For XXH3-64
u64 acc = inputLength * PRIME64_1;
// For XXH3-128
u64 acc[2] = {inputLength * PRIME64_1, 0};
```
### Step 2. Process the input
This step is further divided into two cases: one for 17-128 bytes of input, and one for 129-240 bytes of input.
#### Mixing operation
This step uses a mixing operation that mixes a 16-byte segment of data, a 16-byte segment of secret and the seed into a 64-bit value as a building block. This operation treat the segment of data and secret as little-endian 64-bit values.
```c
mixStep(u8 data[16], size secretOffset, u64 seed):
u64 dataWords[2] = data[0:16];
u64 secretWords[2] = secret[secretOffset:secretOffset+16];
u128 mulResult = (u128)(dataWords[0] xor (secretWords[0] + seed)) *
(u128)(dataWords[1] xor (secretWords[1] - seed));
return lowerHalf(mulResult) xor higherHalf(mulResult);
```
The mixing operation is always invoked in groups of two in XXH3-128, where two 16-byte segments of data are mixed with a 32-byte segment of secret, and the accumulators are updated accordingly.
```c
mixTwoChunks(u8 data1[16], u8 data2[16], size secretOffset, u64 seed):
u64 dataWords1[2] = data1[0:16]; // again, little-endian conversion
u64 dataWords2[2] = data2[0:16];
acc[0] = acc[0] + mixStep(data1, secretOffset, seed);
acc[1] = acc[1] + mixStep(data2, secretOffset + 16, seed);
acc[0] = acc[0] xor (dataWords2[0] + dataWords2[1]);
acc[1] = acc[1] xor (dataWords1[0] + dataWords1[1]);
```
The input is split into several 16-byte chunks and mixed, and the result is added to the accumulator(s).
#### 17-128 bytes of input
The input is read as *N* 16-byte chunks starting from the beginning and *N* chunks starting from the end, where *N* is the smallest number that these 2*N* chunks cover the whole input. These chunks are paired up and mixed, and the results are accumulated to the accumulator(s).
```c
// the loop variable `i` should be signed to avoid underflow in implementation
processInput_XXH3_64_17to128():
u64 numRounds = ((inputLength - 1) >> 5) + 1;
for (i = numRounds - 1; i >= 0; i--) {
size offsetStart = i*16;
size offsetEnd = inputLength - i*16 - 16;
acc += mixStep(input[offsetStart:offsetStart+16], i*32, seed);
acc += mixStep(input[offsetEnd:offsetEnd+16], i*32+16, seed);
}
processInput_XXH3_128_17to128():
u64 numRounds = ((inputLength - 1) >> 5) + 1;
for (i = numRounds - 1; i >= 0; i--) {
size offsetStart = i*16;
size offsetEnd = inputLength - i*16 - 16;
mixTwoChunks(input[offsetStart:offsetStart+16], input[offsetEnd:offsetEnd+16], i*32, seed);
}
```
#### 129-240 bytes of input
The input is split into 16-byte (XXH3-64) or 32-byte (XXH3-128) chunks. The first 128 bytes are first mixed chunk by chunk, followed by an intermediate avalanche operation. Then the remaining full chunks are processed, and finally the last 16/32 bytes are treated as a chunk to process.
```c
processInput_XXH3_64_129to240():
u64 numChunks = inputLength >> 4;
for (i = 0; i < 8; i++) {
acc += mixStep(input[i*16:i*16+16], i*16, seed);
}
acc = avalanche(acc);
for (i = 8; i < numChunks; i++) {
acc += mixStep(input[i*16:i*16+16], (i-8)*16 + 3, seed);
}
acc += mixStep(input[inputLength-16:inputLength], 119, seed);
processInput_XXH3_128_129to240():
u64 numChunks = inputLength >> 5;
for (i = 0; i < 4; i++) {
mixTwoChunks(input[i*32:i*32+16], input[i*32+16:i*32+32], i*32, seed);
}
acc[0] = avalanche(acc[0]);
acc[1] = avalanche(acc[1]);
for (i = 4; i < numChunks; i++) {
mixTwoChunks(input[i*32:i*32+16], input[i*32+16:i*32+32], (i-4)*32 + 3, seed);
}
// note that the half-chunk order and the seed is different here
mixTwoChunks(input[inputLength-16:inputLength], input[inputLength-32:inputLength-16], 103, (u64)0 - seed);
```
### Step 3. Finalization
The final result is extracted from the accumulator(s).
```c
XXH3_64_17to240():
return avalanche(acc);
XXH3_128_17to240():
u64 low = acc[0] + acc[1];
u64 high = (acc[0] * PRIME64_1) + (acc[1] * PRIME64_4) + (((u64)inputLength - seed) * PRIME64_2);
return {avalanche(low), // lower half
(u64)0 - avalanche(high)}; // higher half
```
XXH3 Algorithm Description (for large inputs)
-------------------------------------
This algorithm is used for inputs larger than 240 bytes. The internal hash state is stored inside 8 "accumulators", each one storing an unsigned 64-bit value.
### Step 1. Initialize internal accumulators
The accumulators are initialized to fixed constants:
```c
u64 acc[8] = {
PRIME32_3, PRIME64_1, PRIME64_2, PRIME64_3,
PRIME64_4, PRIME32_2, PRIME64_5, PRIME32_1};
```
### Step 2. Process blocks
The input is consumed and processed one full block at a time. The size of the block depends on the length of the secret. Specifically, a block consists of several 64-byte stripes. The number of stripes per block is `floor((secretLength-64)/8)` . For the default 192-byte secret, there are 16 stripes in a block, and thus the block size is 1024 bytes.
```c
secretLength = lengthInBytes(secret); // default 192; at least 136
stripesPerBlock = (secretLength-64) / 8; // default 16; at least 9
blockSize = 64 * stripesPerBlock; // default 1024; at least 576
```
The process of processing a full block is called a *round*. It consists of the following two sub-steps:
#### Step 2-1. Process stripes in the block
A stripe is evenly divided into 8 lanes, of 8 bytes each. In an accumulation step, one stripe and a 64-byte contiguous segment of the secret are used to update the accumulators. Each lane reads its associated 64-bit value using little-endian convention.
The accumulation step applies the following procedure:
```c
accumulate(u64 stripe[8], size secretOffset):
u64 secretWords[8] = secret[secretOffset:secretOffset+64];
for (i = 0; i < 8; i++) {
u64 value = stripe[i] xor secretWords[i];
acc[i xor 1] = acc[i xor 1] + stripe[i];
acc[i] = acc[i] + (u64)lowerHalf(value) * (u64)higherHalf(value);
// (value and 0xFFFFFFFF) * (value >> 32)
}
```
The accumulation step is repeated for all stripes in a block, using different segments of the secret, starting from the first 64 bytes for the first stripe, and offset by 8 bytes for each following round:
```c
round_accumulate(u8 block[blockSize]):
for (n = 0; n < stripesPerBlock; n++) {
u64 stripe[8] = block[n*64:n*64+64]; // 64 bytes = 8 u64s
accumulate(stripe, n*8);
}
```
#### Step 2-2. Scramble accumulators
After the accumulation steps are finished for all stripes in the block, the accumulators are scrambled using the last 64 bytes of the secret.
```c
round_scramble():
u64 secretWords[8] = secret[secretLength-64:secretLength];
for (i = 0; i < 8; i++) {
acc[i] = acc[i] xor (acc[i] >> 47);
acc[i] = acc[i] xor secretWords[i];
acc[i] = acc[i] * PRIME32_1;
}
```
A round is thus a `round_accumulate` followed by a `round_scramble`:
```c
round(u8 block[blockSize]):
round_accumulate(block);
round_scramble();
```
Step 2 is looped to consume the input until there are less than or equal to `blockSize` bytes of input left. Note that we leave the last block to the next step even if it is a full block.
### Step 3. Process the last block and the last 64 bytes
Accumulation steps are run for the stripes in the last block, except for the last stripe (whether it is full or not). After that, run a final accumulation step by treating the last 64 bytes as a stripe. Note that the last 64 bytes might overlap with the second-to-last block.
```c
// len is the size of the last block (1 <= len <= blockSize)
lastRound(u8 block[], size len, u64 lastStripe[8]):
size nFullStripes = (len-1)/64;
for (n = 0; n < nFullStripes; n++) {
u64 stripe[8] = block[n*64:n*64+64];
accumulate(stripe, n * 8);
}
accumulate(lastStripe, secretLength - 71);
```
### Step 4. Finalization
In the finalization step, a merging procedure is used to extract a single 64-bit value from the accumulators, using an initial seed value and a 64-byte segment of the secret.
```c
finalMerge(u64 initValue, size secretOffset):
u64 secretWords[8] = secret[secretOffset:secretOffset+64];
u64 result = initValue;
for (i = 0; i < 4; i++) {
// 64-bit by 64-bit multiplication to 128-bit full result
u128 mulResult = (u128)(acc[i*2] xor secretWords[i*2]) *
(u128)(acc[i*2+1] xor secretWords[i*2+1]);
result = result + (lowerHalf(mulResult) xor higherHalf(mulResult));
// (mulResult and 0xFFFFFFFFFFFFFFFF) xor (mulResult >> 64)
}
return avalanche(result);
```
XXH3-128 runs the merging procedure twice for the two halves of the result, using different secret segments and different initial values derived from the total input length.
The XXH3-64 result is just the lower half of the XXH3-128 result.
```c
XXH3_64_large():
return finalMerge((u64)inputLength * PRIME64_1, 11);
XXH3_128_large():
return {finalMerge((u64)inputLength * PRIME64_1, 11), // lower half
finalMerge(~((u64)inputLength * PRIME64_2), secretLength - 75)}; // higher half
```
Performance considerations
----------------------------------
@@ -301,6 +802,8 @@ On 64-bit systems, the 64-bit variant `XXH64` is generally faster to compute, so
On 32-bit systems though, positions are reversed: `XXH64` performance is reduced, due to its usage of 64-bit arithmetic. `XXH32` becomes a faster variant.
Finally, when vector operations are possible, `XXH3` is likely the faster variant.
Reference Implementation
----------------------------------------
@@ -312,6 +815,6 @@ It links to the [github project page](https://github.com/Cyan4973/xxHash) where
Version changes
--------------------
v0.7.3: Minor fixes
v0.2.0: added XXH3 specification, by Adrien Wu
v0.1.1: added a note on rationale for selection of constants
v0.1.0: initial release
+11
View File
@@ -0,0 +1,11 @@
#include <stdint.h>
#include "xxhash.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
volatile XXH64_hash_t hash64 = XXH64(data, size, 0);
(void)hash64;
volatile XXH32_hash_t hash32 = XXH32(data, size, 0);
(void)hash32;
return 0;
}
+5 -4
View File
@@ -1,14 +1,15 @@
# xxHash - Extremely fast hash algorithm
# Copyright (C) 2012-2021, Yann Collet, Facebook
# BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
prefix=@PREFIX@
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib
exec_prefix=@EXECPREFIX@
includedir=@INCLUDEDIR@
libdir=@LIBDIR@
Name: xxhash
Description: extremely fast hash algorithm
URL: https://www.xxhash.com/
URL: http://www.xxhash.com/
Version: @VERSION@
Libs: -L${libdir} -lxxhash
Cflags: -I${includedir}
+73 -16
View File
@@ -1,7 +1,35 @@
CFLAGS += -Wall -Wextra -g
# ################################################################
# xxHash Makefile
# Copyright (C) 2012-2021 Yann Collet
#
# GPL v2 License
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# You can contact the author at:
# - xxHash homepage: https://www.xxhash.com
# - xxHash source repository: https://github.com/Cyan4973/xxHash
# ################################################################
CFLAGS += -Wall -Wextra -Wundef -g
CP = cp
NM = nm
GREP = grep
XXHSUM_DIR = ..
XXHSUM = $(XXHSUM_DIR)/xxhsum
# Define *.exe as extension for Windows systems
ifneq (,$(filter Windows%,$(OS)))
@@ -23,7 +51,7 @@ default: all
all: test
.PHONY: test
test: test_multiInclude test_unicode
test: test_multiInclude test_unicode test_sanity
.PHONY: test_multiInclude
test_multiInclude:
@@ -35,20 +63,26 @@ test_multiInclude:
# compile with xxhash.o, to detect duplicated symbols
$(MAKE) multiInclude_withxxhash
@$(MAKE) clean
# Note: XXH_INLINE_ALL with XXH_NAMESPACE is currently disabled
# compile with XXH_NAMESPACE
# CPPFLAGS=-DXXH_NAMESPACE=TESTN_ $(MAKE) multiInclude_withxxhash
# compile with XXH_NAMESPACE before XXH_INLINE_ALL
CPPFLAGS=-DXXH_NAMESPACE=TESTN_ $(MAKE) multiInclude
# no symbol prefixed TESTN_ should exist
# ! $(NM) multiInclude_withxxhash | $(GREP) TESTN_
#$(MAKE) clean
# compile with XXH_NAMESPACE and without xxhash.o
# CPPFLAGS=-DXXH_NAMESPACE=TESTN_ $(MAKE) multiInclude
# no symbol prefixed TESTN_ should exist
# ! $(NM) multiInclude | $(GREP) TESTN_
#@$(MAKE) clean
! $(NM) multiInclude | $(GREP) TESTN_
$(MAKE) clean
# compile xxhash.o with XXH_NAMESPACE
CPPFLAGS=-DXXH_NAMESPACE=TESTN_ $(MAKE) multiInclude_withxxhash
# symbols prefixed TESTN_ should exist in xxhash.o (though not be invoked)
$(NM) multiInclude_withxxhash | $(GREP) TESTN_
$(MAKE) clean
xxhsum$(EXT): ../xxhash.c ../xxhash.h ../xxh3.h ../xxhsum.c
$(CC) $(CFLAGS) $(LDFLAGS) ../xxhash.c ../xxhsum.c -o $@
.PHONY: test_ppc_redefine
test_ppc_redefine: ppc_define.c
@$(MAKE) clean
$(CC) $(CPPFLAGS) $(CFLAGS) -c $^
.PHONY: $(XXHSUM)
$(XXHSUM):
$(MAKE) -C $(XXHSUM_DIR) xxhsum
$(CP) $(XXHSUM) .
# Make sure that Unicode filenames work.
# https://github.com/Cyan4973/xxHash/issues/293
@@ -58,7 +92,7 @@ test_unicode:
@echo "Skipping Unicode test, your terminal doesn't appear to support UTF-8."
@echo "Try with ENABLE_UNICODE=1"
else
test_unicode: xxhsum$(EXT) generate_unicode_test.c
test_unicode: $(XXHSUM) generate_unicode_test.c
# Generate a Unicode filename test dynamically
# to keep UTF-8 out of the source tree.
$(CC) $(CFLAGS) $(LDFLAGS) generate_unicode_test.c -o generate_unicode_test$(EXT)
@@ -66,6 +100,28 @@ test_unicode: xxhsum$(EXT) generate_unicode_test.c
$(SHELL) ./unicode_test.sh
endif
.PHONY: test_filename_escape
test_filename_escape: $(XXHSUM)
./filename-escape.sh
.PHONY: test_cli_comment_line
test_cli_comment_line: $(XXHSUM)
$(SHELL) ./cli-comment-line.sh
.PHONY: test_cli_ignore_missing
test_cli_ignore_missing: $(XXHSUM)
$(SHELL) ./cli-ignore-missing.sh
.PHONY: test_sanity
test_sanity: sanity_test.c
$(CC) $(CFLAGS) $(LDFLAGS) sanity_test.c -o sanity_test$(EXT)
$(RUN_ENV) ./sanity_test$(EXT)
.PHONY: sanity_test_vectors.h
sanity_test_vectors.h: sanity_test_vectors_generator.c
$(CC) $(CFLAGS) $(LDFLAGS) sanity_test_vectors_generator.c -o sanity_test_vectors_generator$(EXT)
./sanity_test_vectors_generator$(EXT)
xxhash.o: ../xxhash.c ../xxhash.h
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -c -o $@ $<
@@ -75,4 +131,5 @@ multiInclude_withxxhash: multiInclude.o xxhash.o
clean:
@$(RM) *.o
@$(RM) multiInclude multiInclude_withxxhash
@$(RM) *.unicode generate_unicode_test$(EXT) unicode_test.* xxhsum$(EXT)
@$(RM) *.unicode generate_unicode_test$(EXT) unicode_test.* xxhsum*
@$(RM) sanity_test$(EXT) sanity_test_vectors_generator$(EXT)
+1
View File
@@ -4,6 +4,7 @@
benchHash
benchHash32
benchHash_avx2
benchHash_avx512
benchHash_hw
# test files
Loaded 100 of 519 files, more files were not shown because too many files have changed in this diff. Show more