Compare commits

...
Author SHA1 Message Date
SirKnightly 9a07486866 Automated build commit 2021-05-03 02:32:09 +00:00
Goober5000 28f60df7fa Merge pull request #3406 from MageKing17/bugfix/avoid-negative-lookup-in-loadout
Avoid negative lookup when parsing loadouts.
2021-04-25 19:00:44 -04:00
MageKing17 bed18012d6 Avoid negative lookup when parsing loadouts.
#3271 changed the logic of `stuff_token_list()` in such a way that the supplied index being used to access an array was no longer skipped if it was invalid; naturally, this means that this warning was now being inevitably followed up by an out-of-bounds array access. Adding a `!skip_this_entry` check should hopefully fix the problem while still allowing the loadout count parsing code below it to run, which was presumably the reason the `continue` statement was replaced with the `skip_this_entry` variable in the first place. Fixes #3405.
2021-04-25 11:10:55 -07:00
Goober5000 d43f30053d Merge pull request #3404 from scp-fs2open/revert-3400-apng_fix
Revert "Fix APNG Animation Framecounter"
2021-04-24 22:43:40 -04:00
MageKing17 76dccbe07d Revert "Fix APNG Animation Framecounter" 2021-04-24 18:53:52 -07:00
Goober5000 3eafcde138 Merge pull request #3403 from MageKing17/bugfix/avoid-shiphit-negative-array-access
Avoid out-of-bounds array access if killed by a parentless weapon.
2021-04-24 21:13:38 -04:00
Goober5000 ca7065df46 Merge pull request #3400 from BMagnu/apng_fix
Fix APNG Animation Framecounter
2021-04-24 18:39:39 -04:00
Goober5000 cedf66cb31 Merge pull request #3402 from Baezon/fix-edge-checks
Fix fov_edge_checks
2021-04-24 18:39:32 -04:00
Baezon 03a3fbdc1c fix fov edge checks 2021-04-24 17:10:20 -04:00
MageKing17 9c6661e0e8 Avoid out-of-bounds array access if killed by a parentless weapon.
While there's code to avoid accessing the parent object of a parentless beam, there's no equivalent code to avoid accessing the parent object of a parentless weapon. This fixes this inconsistency.
2021-04-24 13:11:35 -07:00
Birk Magnussen 6bea921fbe Add short explanation 2021-04-24 23:04:00 +09:00
Birk Magnussen 79f5eda0d6 Fix APNG Animation Framecounter 2021-04-24 16:00:09 +09:00
Goober5000 3aa61dfccb Merge pull request #3396 from Goober5000/is_visible_tweak
make is-ship-visible default to the first player
2021-04-20 00:00:31 -04:00
Tyler Blount 0febfb3545 Merge pull request #3394 from JohnAFernandez/Fix-that-annoying-fred-freezes-when-open-too-long-bug
Keep Fred from freezing
2021-04-19 21:18:48 -06:00
Goober5000 e1c8f5d2ed make is-ship-visible default to the first player
To be more user-friendly, and to accommodate buggy retail missions, make the one-argument version of `is-ship-visible` default to the first player in multiplayer mode..  Also, change the warning to an mprintf.
2021-04-19 23:04:27 -04:00
JohnAFernandez 44343f8d1e Put a bandaid on Fred freezing
Could be because of variable overflows or from `thistime` somehow being much smaller than `lasttime`.

Hard to find the root cause, but manually setting the memory to bad values will no longer cause the freezing with this patch.
2021-04-19 22:00:46 -04:00
Taylor Richards 424c69d1e5 Merge pull request #3379 from notimaginative/fix_chat_error_handling
address issues with error handling in chat_api
2021-04-18 19:46:39 -04:00
JohnAFernandez 6d1354f1f6 Explicitly check that the type is a ship. (#3389)
Not all ships in the ships array are ships (if they were turned into observers), so we need to explicitly check that they are ships.
2021-04-18 05:11:30 +00:00
Tyler Blount d5c4f3e5c7 Merge pull request #3348 from TRBlount/fix/display_name_regression
Strip hashes from explicitly defined display names in tables.
2021-04-17 23:03:54 -06:00
JohnAFernandez 89bd64f4ab Make sure the Netgame state is set to prevent a crash (#3339)
If the client tries to respawn a player when the server is trying to end the game it will lead to a crash on the client side.  This sets the client's game to the correct state when an end game packet is received and adds extra checks before respawning.
2021-04-17 23:49:54 -04:00
Tyler Blount 417739665c Strip hashes from explicitly defined ship and weapon display names 2021-04-17 17:07:41 -06:00
MageKing17 e236a79773 Make an invalid variable name throw an error. (#3373)
There were a few assertions in the SEXP code that would trip if an invalid variable name were specified in a SEXP, but nothing that actually stopped a Release build from performing an out-of-bounds array access if someone made a typo in notepad. Since, as far as I could tell, everything should go through `get_sexp_text_for_variable()` first, I changed its `Assert()` into an `Error()` that should hopefully ensure that we avoid ever doing anything with `Sexp_variables[-1]`.
2021-04-14 21:26:11 -04:00
JohnAFernandez d523f0aef3 Make Sure Special Shield Hitpoint Max Gets Transferred (#3383)
Since the shield strength of the ships is being copied, you need to copy the special shield hitpoints, too, just like for hull.
2021-04-14 21:07:31 -04:00
Taylor Richards 697c009fb3 address issues with error handling in chat_api:
- detect server connection error messages before blindly
   moving to user login (crash fix)
 - detect read errors and fail accordingly (crash fix)
 - allow server disconnect to run even if we aren't connected (cleanup & reset)
2021-04-12 12:59:04 -04:00
JohnAFernandez 1f918fd4c6 Allow Fred to Edit and Allow Command briefs in FRED (#3372)
* Allow Fred to Edit and Allow Command briefs in FRED

They are currently allowed in the game, but not being allowed in Fred was an oversight of mine.

* Allow Command brief saving in qtFRED
2021-04-11 13:50:25 -04:00
Asteroth 3ea7a6d1ba Merge pull request #3369 from Baezon/cull-generic-debris
Properly cull generic debris
2021-04-10 21:44:56 -04:00
Baezon 633cd88e83 modernize use nullptr 2021-04-10 19:38:18 -04:00
Baezon 7431aba995 properly cull generic debris 2021-04-09 21:35:26 -04:00
JohnAFernandez 328bebe83a Fix event parsing by setting flags to zero before loading. (#3363) 2021-04-07 23:41:14 -04:00
Goober5000 94e4f3d4cd Merge pull request #3362 from Baezon/no-ship-subsys-lookup
Remove unecessary ship_get_subsys in model_rotate_gun
2021-04-06 10:48:09 -04:00
Baezon b57573c439 remove unecessary ship-get-subsys 2021-04-06 02:24:05 -04:00
Goober5000 0b1d1eed56 Merge pull request #3357 from notimaginative/fix_briefing_music_reset
Only close common_select when we should
2021-04-05 23:52:35 -04:00
Goober5000 123feba557 Merge pull request #3353 from Goober5000/escape_exclamation
make double-character consolidation reusable, and reuse it
2021-04-05 23:50:39 -04:00
Taylor Richards 8c64d73a18 Merge pull request #3358 from notimaginative/fix_main_hall_sounds_in_multi
fix main hall sounds/music not getting stopped on multi clients
2021-04-04 08:19:43 -04:00
Taylor Richards e156f15561 fix main hall sounds/music not getting stopped on multi clients 2021-04-03 11:08:28 -04:00
Taylor Richards 3e1d89ba53 only close common_select when we should 2021-04-03 10:22:11 -04:00
Asteroth 4f7bad2a5c Merge pull request #3347 from Baezon/fireball-lod-fix
Make fireballs default to 1 LOD
2021-04-02 16:01:39 -04:00
Goober5000 dd621e8904 Merge pull request #3351 from PhantomHoover/feature/profile-script-hooks
Add profiling trace for scripting hooks
2021-04-02 15:07:17 -04:00
Goober5000 396d2c55a9 make double-character consolidation reusable, and reuse it
This moves the ## to # escape sequence logic from `mission_process_alt_types` to its own function where it can be used elsewhere (such as for ship class and weapon class display names that need to do the same thing).  Also, this introduces a !! escape sequence for exclamation points that is needed for exclamation points to be used in scripts, as @naomimyselfandi pointed out.
2021-04-02 00:16:19 -04:00
Phantom Hoover 782f6f100d Add profiling trace for scripting hooks 2021-04-01 11:54:09 +01:00
Baezon 4f76c441d6 default to 1 lod 2021-03-31 18:00:00 -04:00
Asteroth a2bd895b7b Merge pull request #3344 from Baezon/fix-huge-targeting-regression
Fix regression with huge/small only targeting
2021-03-31 16:47:17 -04:00
JohnAFernandez a4cf53694d Merge pull request #3346 from JohnAFernandez/Fix-3007
Add a safety check to the $On Frame: Hook
2021-03-31 16:46:11 -04:00
JohnAFernandez 6bd7a43e3d Add a safety check to the $On Frame: Hook
So #3007 is a larger bug than just trying to access the player's target.  The real problem is that the game state is not changed from `GS_STATE_GAME_PLAY` during the mission load when restarting the mission.  So the script thinks it's in the mission, tries to access the target and then crashes.  But this won't be the only bug.  Any script that tries to access data on Frame will run into possible problems on mission restart.
2021-03-31 15:25:38 -04:00
Baezon fffc0ebf8b fix name of class #3344 2021-03-30 22:03:25 -04:00
Goober5000 f2426de80b Merge pull request #3340 from Goober5000/num_valid_arguments_fix
make num-valid-arguments work for the for-* sexps
2021-03-30 19:32:26 -04:00
Goober5000 27f6088117 make num-valid-arguments work for the for-* sexps
This adds a hook into the for-* handlers to return the number of valid arguments.  Fixes a bug reported on Discord.
2021-03-30 18:51:24 -04:00
Goober5000 30c76f36ce Merge pull request #3342 from Goober5000/message_list_saving
modify saving of edited messages
2021-03-30 18:42:39 -04:00
Goober5000 35094851f2 modify saving of edited messages
Instead of saving based on the m_cur_msg index, which may have been reset to -1, save on the most recent positive index.  This should keep track of modified text and dropdowns even when m_cur_msg is set to -1 when the message list loses focus.

Fixes #3308.
2021-03-30 17:32:02 -04:00
Fabian Woltermann b562cf822e Merge pull request #3345 from Baezon/fix-strafing-bug
My kingdom for a semicolon!
2021-03-30 09:15:42 +02:00
Baezon 62942557d5 typo 2021-03-30 00:19:53 -04:00
Baezon 4d68bed436 fix huge targeting regression 2021-03-29 22:42:50 -04:00
Asteroth 19d5b8e68e Merge pull request #3329 from PhantomHoover/feature/split-profile-columns
Split frame profile trace into two onscreen columns if needed
2021-03-29 15:34:55 -04:00
Goober5000 9dc50706a7 Merge pull request #3309 from Baezon/turret-alt-math-fix
Update Turret_alt_math for moving subsystems
2021-03-28 18:06:05 -04:00
Goober5000 f2a0e35959 Merge pull request #3333 from Goober5000/no_xstr_entry_suppress
log missing XSTR strings only once
2021-03-28 15:17:24 -04:00
JohnAFernandez e637eea2fb Merge pull request #3337 from JohnAFernandez/Interpolation-Bug
Fix a rare but eventual crash in the interpolation code.
2021-03-28 10:00:47 -04:00
Fabian Woltermann f3e3769056 Merge pull request #3266 from The-E/fix/3250_dynamic_nebula_detail
Make nebula poof detail settings partially dynamic
2021-03-28 13:18:26 +02:00
JohnAFernandez e218f687a9 Fix a rare but eventual crash in the interpolation code.
I don't know when this was introduced but the bug is extremely obvious once someone hit the crash.  It should just be using the timestamp that the packet was received, not trying to put that timestamp into a vector whose index is server frame numbers.
2021-03-28 05:07:27 -04:00
Baezon 5e10fccdbf Merge remote-tracking branch 'upstream/master' into turret-alt-math-fix 2021-03-27 21:12:30 -04:00
Goober5000 12672d0c2b Merge pull request #3310 from Baezon/fix-fov-edge-checks
Fix Fov_edge_checks
2021-03-27 17:22:37 -04:00
Goober5000 de7081fbb3 Merge pull request #3335 from Goober5000/missing_hud_gauge_warning
change reticle log statements to warnings
2021-03-27 15:19:47 -04:00
Goober5000 d73e4d4dec change reticle log statements to warnings
Most guages in hud_guages.tbl will display a Warning if they can't be loaded, but the reticle is an exception - it only prints a log statement.  This PR changes it to be consistent with the rest of the HUD gauges.

Fixes #3090.
2021-03-27 14:19:59 -04:00
Fabian Woltermann aeefcb4657 Remove an unused constant 2021-03-27 16:23:35 +01:00
Fabian Woltermann 023dcfca76 Use the screen size as the break value, remove it from the Neb detail settings 2021-03-27 16:22:20 +01:00
Fabian Woltermann c6e9f954f0 Use the screen size as the break_* value 2021-03-27 16:11:26 +01:00
Fabian Woltermann 961d5eb171 Use bitmap height * 2 to make sure only completely off-screen poofs are culled 2021-03-27 16:11:26 +01:00
Fabian Woltermann 1a66c97c2e After loading the nebula poofs, resize the break_x and break_y values so they are equal to the largest poof bitmap in use.
Also reduce the break alpha value by 90% for all detail levels.
2021-03-27 16:11:26 +01:00
Goober5000 00e2c2ad52 log missing XSTR strings only once
The "No XSTR entry in strings.tbl for index %d" message was previously printed to the log every time the string was accessed, which for commonly-used strings will clutter up the log.  This makes the message only appear once per missing index.
2021-03-26 23:22:06 -04:00
JohnAFernandez 8991fc67cd Merge pull request #3331 from JohnAFernandez/Fix-Multi-Gamestate-Bug
Check for these states
2021-03-26 20:47:40 -04:00
JohnAFernandez 7641abf41c Check for these states
Because GS_STATE_MULTI_MISSION_SYNC is actually shared for a few different multi screens.
2021-03-26 20:18:39 -04:00
Phantom Hoover 871f7a822e Split frame profile trace into two onscreen columns if needed 2021-03-26 20:33:01 +00:00
m!m ca66664eac Merge pull request #3327 from Shivansps/over_alloc_fix
fix over alloc to store lz4 offsets
2021-03-26 18:33:21 +01:00
m!m 4c1b3551b4 Merge pull request #3328 from ngld/fix/keep_stdout
Add FSO_KEEP_STDOUT env var to skip the AttachConsole() call
2021-03-26 18:32:34 +01:00
Asteroth 07d47cb984 Merge pull request #3319 from Baezon/add-fog-color
Allow for setting of nebula fog color explicitly
2021-03-25 21:20:55 -04:00
Allen A. Babb ce9ee8c264 Merge pull request #3324 from z64555/fix/issue_3322
Fixes #3322
2021-03-25 18:43:15 -05:00
ngld 8039650248 Add FSO_KEEP_STDOUT env var to skip the AttachConsole() call
Fixes #3317
2021-03-26 00:03:51 +01:00
Shivansps cd2b578a1b fix over alloc to store offsets 2021-03-25 19:57:48 -03:00
z64555 85ec8251e3 When in bind mode, identify mouse as CID_JOY0 instead of CID_MOUSE. Fixes #3322. 2021-03-25 09:41:37 -05:00
JohnAFernandez 7e51a13c3a Merge pull request #3296 from Shivansps/compressed-files
LZ4 Compressed files Support
2021-03-25 07:08:06 -04:00
Baezon 538b2c6c95 handle lab and use empty string #3319 2021-03-24 13:25:16 -04:00
wookieejedi d3a70e8ed6 Merge pull request #3320 from wookieejedi/disable-spew-whole-ship
Add `no impact debris` for whole ship
2021-03-24 00:56:09 -04:00
Baezon 9dc68849d6 unused variable 2021-03-23 23:59:05 -04:00
wookieejedi b6bab87601 restore original comment 2021-03-23 23:44:03 -04:00
wookieejedi b8d868f828 restore comment 2021-03-23 23:43:31 -04:00
wookieejedi 01e6a57aaa remove un-needed section 2021-03-23 23:41:57 -04:00
wookieejedi e0fe9227aa clarify whitespace 2021-03-23 23:21:40 -04:00
Baezon 803751959a rename variable for no shadowing 2021-03-23 23:20:11 -04:00
wookieejedi 9597b5962e clarify ship override for subsystems debris 2021-03-23 23:16:59 -04:00
wookieejedi 792f74b33e Add no impact debris flag for entire ship model
Previously `no impact debris` flag was only an option for use on subsystems. This PR adds that flag for the entire ship. It also turns off the impact spew of debris for all subsystems if enabled on the ship.
2021-03-23 23:04:08 -04:00
Baezon 5181e71dab Add explicit fog color 2021-03-23 22:57:54 -04:00
JohnAFernandez 3d0e0f80ae One more hiccup 2021-03-23 20:31:04 -04:00
JohnAFernandez 251125913a How many mistakes is it now? No idea. 2021-03-23 20:31:04 -04:00
JohnAFernandez 89d2d6ed46 Fix missile indicators not going away
Add the should be dead flag, in order to properly make the missiles go away, and not just detonate.
2021-03-23 20:31:04 -04:00
JohnAFernandez 06f198afc1 Forgot one 2021-03-23 20:31:04 -04:00
JohnAFernandez 19a289539a More Whitepsace and Dealing with Crazy old CI 2021-03-23 20:31:04 -04:00
JohnAFernandez c14653b391 Whitespace Adjustments 2021-03-23 20:31:04 -04:00
JohnAFernandez 2527bf31c7 Upgrade velocity compression in OO packet
Previously, the velocity could be off by up to 1 m/s.  This gives that packing function one more byte to work with, so that we have a lot more accuracy to work with.
2021-03-23 20:31:04 -04:00
JohnAFernandez 184107283a Properly Set net_signatures for wing ships
Previously wing ships were being given a net signature that was one too large.
2021-03-23 20:31:04 -04:00
JohnAFernandez 42c19cdfee Fix Missile Syncing Between Server and Client 2021-03-23 20:31:04 -04:00
JohnAFernandez 3830534978 Fix implementation of multi_pack_unpack_desired_vel_and_desired_rotvel 2021-03-23 20:31:04 -04:00
JohnAFernandez 48eef6566d Multi Version bump for 21_2
since many of the fixes and features require a multi bump.
2021-03-23 20:31:04 -04:00
the-maddin b253442545 Add -pilot cmdline flag (#3316)
* Cmdline parsing for `-pilot "<name>"`

Add cmdline parameter `-pilot` with required
argument name and export name as global var
`Cmdline_pilot`.

* Expose to scripting `isAutoselect`

Setting `-pilot` flag sets `ui.isAutoselect()` true
(as does `-benchmark_mode`).

* Skip pilot selection

and call `player_finish_select` with the given
player instead.

* More useful error message on pilot load error

Also display callsign

* Add pilot name as scripting variable

* Don't expose pilot flag to launchers

* make stored flag param `const`
2021-03-22 21:14:57 +00:00
JohnAFernandez 1d5e9794d6 Merge pull request #3263 from BMagnu/fix_unicode_stringstbl
Fix strings.tbl in unicode mode
2021-03-21 17:41:55 -04:00
Asteroth b7a9f545fd Merge pull request #3304 from BMagnu/weapon_penetrate_flag
Add pierce ship weapon flag
2021-03-21 15:12:45 -04:00
JohnAFernandez 9541e244d1 Make sure objects and ships get cleared if leaving mission sync (#3314)
This properly clears ships if you are leaving the sync state for any other state besides the gameplay state.
2021-03-21 14:54:32 -04:00
Asteroth f12d202afe Merge pull request #3278 from Baezon/exponential-fog
Switch to exponential fog and other nebula visibility improvements
2021-03-20 16:45:24 -04:00
Goober5000 507a5f1de8 Merge pull request #3312 from Goober5000/per_mission_chase_view
add mission flag for starting missions in chase view
2021-03-20 15:36:11 -04:00
Baezon 3810b039f5 Merge remote-tracking branch 'upstream/master' into exponential-fog 2021-03-20 10:39:41 -04:00
Baezon 827754d6de minor fixes 2021-03-20 02:31:47 -04:00
Goober5000 d455e17e34 add mission flag for starting missions in chase view
Follow-up to #3305.  Some mods may want one or two missions to start in chase view without having every single mission default to chase view.  So this adds a mission flag (with FRED and qtFRED support) that will enable this on a per-mission basis.
2021-03-20 00:21:27 -04:00
Shivansps db360820a9 fix build check 2021-03-19 20:51:09 -03:00
Baezon 804a222041 unused variable 2021-03-19 19:44:11 -04:00
Shivansps 6dab1e464f Merge branch 'compressed-files' of https://github.com/Shivansps/fs2open.github.com into compressed-files 2021-03-19 20:21:02 -03:00
Shivansps 86c45309e8 requested changes and simplified if on random access function 2021-03-19 20:20:58 -03:00
Birk Magnussen 4f4690a482 Fix Names and spawn on destruct 2021-03-20 03:52:54 +09:00
Baezon 1ca60e1d2f fix fov_edge_checks 2021-03-19 11:48:15 -04:00
Birk Magnussen 011f7e4d6c Change flag to Table entry 2021-03-19 18:30:39 +09:00
Baezon eb538ffba8 update turret_alt_math for moving subsystems 2021-03-19 02:13:20 -04:00
Birk Magnussen 2a73fb340f Add pierce ship weapon flag 2021-03-17 17:39:04 +09:00
Shivansps ad60240eb6 Updated comment header. Feature Complete. 2021-03-16 10:11:48 -03:00
Shivansps f8df97b489 fix seek_end on comp_fseek
This where causing the pcx issues
2021-03-15 23:59:39 -03:00
Shivansps d5feddfb8a fixed comp_fseek return 2021-03-15 20:08:58 -03:00
Baezon f5e32fa1a2 Merge remote-tracking branch 'upstream/master' into exponential-fog 2021-03-15 02:27:22 -04:00
Shivansps 9fa3baa458 fix typo 2021-03-14 23:43:22 -03:00
Shivansps 4b3760dfb4 more build fixes 2021-03-14 21:17:07 -03:00
Shivansps 142d586a1c and even more build check fixes 2021-03-14 20:29:26 -03:00
Shivansps 95103dfcb8 more build check fixes 2021-03-14 19:57:04 -03:00
Shivansps f50ea26051 Change CI struct name to upper case 2021-03-14 19:36:20 -03:00
Shivansps 983dd0b6ca changes for build check errors 2021-03-14 19:21:13 -03:00
Shivansps 3bdc5e0c27 Merge branch 'master' into compressed-files 2021-03-14 17:57:53 -03:00
Shivansps ba6a471054 comment debug statements 2021-03-14 14:55:20 -03:00
Shivansps ce44e3522b updated header 2021-03-14 14:35:04 -03:00
Shivansps c1b87bc2b6 Add missing CAP to comp goal position.
It should not be needed but at least this stops crashing when you use a unsupported format in compression (like, audio and pcx)
2021-03-14 13:34:13 -03:00
Shivansps 1f164dbb64 Removed isCompressed from compression_info 2021-03-14 11:12:00 -03:00
Shivansps 1275cbfd83 Proper lz4 reference and added position checks
LZ4 moved to lib folder and added cmakelists.
Added several position check to match cfilearchive ones for compressed files.
Changed header check to int.
2021-03-14 10:47:11 -03:00
Shivansps 20cccdbf20 Updated Implementation
Moved the compression functions to separated files, added dynamic blocksize support for LZ4 and a decoder buffer to make sure every block is only read from file and decoded only once.
2021-03-13 17:15:04 -03:00
Shivansps 077338086a Improved implementation
Model load and tech room now works, it crashes at mission load.
2021-03-12 19:58:49 -03:00
Birk Magnussen 0b2ee5f76b Modify other file reading method for new encoding conversion 2021-03-13 07:50:41 +09:00
Shivansps 3f9218e671 1st attempt at implementation
I just dumped everything into cfilearchive to avoid a fight with the includes that i cant win for now.

It dosent work, DDS utils complains about DDS filecode.
2021-03-11 20:51:28 -03:00
Birk Magnussen 3003d0589d Change validation to own function 2021-03-12 06:34:27 +09:00
Birk Magnussen 4bd15d43da Fix Warning due to enum class 2021-03-12 06:04:10 +09:00
Birk Magnussen 8df62e99f5 Change Enum to Enum Class 2021-03-12 05:54:25 +09:00
Birk Magnussen d93c9c4220 Adapt parsing exceptions 2021-03-12 05:45:09 +09:00
Birk Magnussen 1b5fd3c5fd Move Conversion functions to util/unicode 2021-03-12 05:42:44 +09:00
Shivansps 8292d8c44a Revert "Merge branch 'arm_fixes'"
This reverts commit 2ee128cd88, reversing
changes made to a2b349855e.
2021-03-09 20:44:43 -03:00
Baezon 78c79ac88d debug clean up 2021-03-08 01:37:00 -05:00
Baezon 6e54ed3dfc more exponential fog 2021-03-08 00:09:42 -05:00
Baezon 3c53b74e5e switch to exponential nebula fog 2021-03-04 23:02:24 -05:00
Birk Magnussen 829e0b8b7c remove bad type modifier 2021-03-04 22:17:16 +09:00
Birk Magnussen 4b60ca467c Refactor encoding functions 2021-03-04 22:08:50 +09:00
Birk Magnussen b45cb19f3c Add changes to the parse exceptions to work with utf8 encoding 2021-03-02 00:05:12 +09:00
Birk Magnussen e30c919286 Add encoding conversion helpers 2021-03-02 00:03:36 +09:00
Shivansps 2ee128cd88 Merge branch 'arm_fixes' 2021-02-19 21:02:53 -03:00
Shivansps a2b349855e Merge pull request #1 from scp-fs2open/master
Update fork
2021-02-19 20:53:22 -03:00
Shivansps 1239ec47e3 Smart pointers and disabled some messages
Added smart pointers to bsp_in, bsp_out, sldc_tree and slc2_tree as requested.

I also changed the #error to #pragma message in a attempt to remove the false positive error.

Also did minor code indent fixes-
2020-08-30 13:45:43 -03:00
Shivansps eb1814e303 SLC2 and POF version 2118 support
Changed SLDC system to SLC2, this replaced the char at the beginning of the node for an int in order for the tree to be aligned.
Added BSP_Defpoints data alignment and SLDC to SLC2 conversion for pof version < 2118.
2020-08-27 20:10:29 -03:00
94 changed files with 10825 additions and 666 deletions

No files matched your search

+1
View File
@@ -26,6 +26,7 @@ TARGET_LINK_LIBRARIES(code PUBLIC openal)
TARGET_LINK_LIBRARIES(code PUBLIC ${LUA_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${PNG_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC ${JPEG_LIBS})
TARGET_LINK_LIBRARIES(code PUBLIC lz4)
TARGET_LINK_LIBRARIES(code PUBLIC sdl2)
+1 -1
View File
@@ -1448,7 +1448,7 @@ void ai_big_strafe_attack()
if (ai_new_maybe_reposition_attack_subsys())
return;
} else if (ai_big_maybe_follow_subsys_path(0))
return
return;
ai_big_attack_get_data(&target_pos, &target_dist, &target_dot);
if ( ai_big_strafe_maybe_retreat(&target_pos) )
+66 -141
View File
@@ -87,6 +87,18 @@ typedef struct eval_enemy_obj_struct {
int nearest_objnum;
} eval_enemy_obj_struct;
// the current world orientation of the turret matrix, corresponding to its fvec and uvec defined in the model
// is NOT affected by the turret's current aiming
void turret_instance_find_world_orient(matrix* out_mat, int model_instance_num, int submodel_num, const matrix* objorient)
{
auto pmi = model_get_instance(model_instance_num);
auto pm = model_get(pmi->model_num);
vec3d fvec, uvec;
model_instance_find_world_dir(&fvec, &pm->submodel[submodel_num].frame_of_reference.vec.fvec, pm, pmi, pm->submodel[submodel_num].parent, objorient);
model_instance_find_world_dir(&uvec, &pm->submodel[submodel_num].frame_of_reference.vec.uvec, pm, pmi, pm->submodel[submodel_num].parent, objorient);
vm_vector_2_matrix_norm(out_mat, &fvec, &uvec);
}
/**
* Is object in turret field of view?
*
@@ -98,124 +110,53 @@ typedef struct eval_enemy_obj_struct {
*
* @return 1 if objp is in fov of the specified turret. Otherwise return 0.
*/
int object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist)
bool object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist)
{
vec3d v2e;
float size_mod;
bool in_fov;
bool in_fov = false;
if (ss->flags[Ship::Subsystem_Flags::FOV_edge_check]) {
int model_num;
switch (objp->type) {
case OBJ_SHIP:
model_num = Ship_info[Ships[objp->instance].ship_info_index].model_num;
break;
case OBJ_ASTEROID:
model_num = Asteroid_info[Asteroids[objp->instance].asteroid_type].model_num[Asteroids[objp->instance].asteroid_subtype];
break;
default:
vm_vec_normalized_dir(&v2e, &objp->pos, tpos);
size_mod = objp->radius / (dist + objp->radius);
in_fov = turret_fov_test(ss, tvec, &v2e, size_mod);
return in_fov;
}
auto pm = model_get(model_num);
for (int i = 0; i < 8; i++) {
vec3d bbox_point;
vm_vec_unrotate(&bbox_point, &pm->bounding_box[i], &objp->orient);
bbox_point += objp->pos;
vm_vec_normalized_dir(&v2e, &bbox_point, tpos);
in_fov = turret_fov_test(ss, tvec, &v2e, -0.2f);
if (in_fov)
return true;
}
}
// if the bbox points method didn't work (or fov_edge_checks isn't on)
// try the normal method
vm_vec_normalized_dir(&v2e, &objp->pos, tpos);
size_mod = objp->radius / (dist + objp->radius);
in_fov = turret_fov_test(ss, tvec, &v2e, size_mod);
if ( in_fov ) {
return 1;
}
return 0;
}
bool is_object_radius_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, vec3d *v2e, vec3d *predicted_pos, float distance)
{
float target_dist = distance;
if (distance == 0.0f)
target_dist = vm_vec_dist(predicted_pos,tpos);
if (object_in_turret_fov(objp, ss, tvec, tpos, target_dist + objp->radius)) {
// so the targeted spot in not in fov but the enemy + radius is
// lets align the darn gun and try shooting there
vec3d temp_vec;
float multiplier = 0;
model_subsystem *tp = ss->system_info;
// project v2e_from_turret to turret normal
// substract resultant vector from the temp_vec (v2e_from_turret)
// adjust z component as necessary
// calculate multiplier for the resultant vector
// use multiplier and the z component and compose a new vector
float dot = vm_vec_dot(v2e, tvec);
vm_vec_scale_add(&temp_vec, v2e, tvec, -dot);
if (IS_VEC_NULL_SQ_SAFE(&temp_vec)) {
// return false, target is perfectly aligned over or below the turret
// safe bet is to allow turret to reacquire better target
return false;
}
// normalize the vec, it needs to be done regardless
vm_vec_normalize(&temp_vec);
bool fix_elevation = false;
bool fix_base_rot = false;
if (dot < tp->turret_fov) {
dot = tp->turret_fov;
fix_elevation = true;
}
if (dot > tp->turret_max_fov) {
dot = tp->turret_max_fov;
fix_elevation = true;
}
if (tp->flags[Model::Subsystem_Flags::Turret_alt_math]) {
// Since we no longer maintain world_to_turret_matrix, regenerate it here.
vec3d turret_norm;
matrix turret_matrix, world_to_turret_matrix;
model_instance_find_world_dir(&turret_norm, &tp->turret_norm, Ships[objp->instance].model_instance_num, tp->subobj_num, &vmd_identity_matrix);
vm_vector_2_matrix(&turret_matrix, &turret_norm, nullptr, nullptr);
vm_matrix_x_matrix(&world_to_turret_matrix, &objp->orient, &turret_matrix);
vec3d temp_vec2;
vm_vec_rotate(&temp_vec2, &temp_vec, &world_to_turret_matrix);
// now in turrets frame of reference
// check if math is actually possible
if (!((temp_vec2.xyz.x == 0) && (temp_vec2.xyz.y == 0))) {
float temp_z = temp_vec2.xyz.z;
temp_vec2.xyz.z = 0.0f;
// make sure null vecs wont happen
if (!IS_VEC_NULL_SQ_SAFE(&temp_vec2)) {
vm_vec_normalize(&temp_vec2);
// only do this if it actually is required
if (-temp_vec2.xyz.y < tp->turret_y_fov) {
float check_pos = 1;
fix_base_rot = true;
temp_vec2.xyz.y = -tp->turret_y_fov;
if (temp_vec2.xyz.x < 0)
check_pos = -1;
temp_vec2.xyz.x = check_pos * sqrtf(1 - (temp_vec2.xyz.y*temp_vec2.xyz.y));
// restore z component
float scaler = sqrtf(1 - (temp_z*temp_z));
vm_vec_scale(&temp_vec2,scaler);
temp_vec2.xyz.z = temp_z;
// back to world frame
vm_vec_unrotate(&temp_vec, &temp_vec2, &world_to_turret_matrix);
}
}
}
}
if (fix_elevation || fix_base_rot) {
if (fix_elevation) {
multiplier = sqrtf(1 - (dot*dot));
// keep the temp_vec scaled with the tweaked vector
vm_vec_scale(&temp_vec, multiplier);
}
vm_vec_scale_add(v2e, &temp_vec, tvec, dot);
// and we are done with v2e...
vm_vec_scale_add(predicted_pos, tpos, v2e, target_dist);
// and we are done with predicted position
return true;
} else {
mprintf(("Warning: Function 'is_object_radius_in_turret_fov' was called\nwithout need to fix turret alignments\n"));
return false;
}
}
// outside of the expanded radii, unable to align, return false
return false;
return in_fov;
}
/**
@@ -1196,17 +1137,11 @@ int find_turret_enemy(ship_subsys *turret_subsys, int objnum, vec3d *tpos, vec3d
if ( tagged_only_flag && ship_is_tagged(&Objects[aip->target_objnum]) ) {
// select new target if aip->target_objnum is out of field of view
vec3d v2e;
float dist;
bool in_fov;
dist = vm_vec_normalized_dir(&v2e, &Objects[aip->target_objnum].pos, tpos);
vm_vec_normalized_dir(&v2e, &Objects[aip->target_objnum].pos, tpos);
in_fov = turret_fov_test(turret_subsys, tvec, &v2e);
if (turret_subsys->flags[Ship::Subsystem_Flags::FOV_edge_check]) {
if (in_fov == false)
if (object_in_turret_fov(&Objects[aip->target_objnum], turret_subsys, tvec, tpos, dist + Objects[aip->target_objnum].radius))
in_fov = true;
}
// MODIFY FOR ATTACKING BIG SHIP
// dot += (0.5f * Objects[aip->target_objnum].radius / dist);
if (in_fov) {
@@ -1256,7 +1191,7 @@ void ship_get_global_turret_info(const object *objp, const model_subsystem *tp,
if (gpos)
model_instance_find_world_point(gpos, &vmd_zero_vector, model_instance_num, tp->subobj_num, &objp->orient, &objp->pos);
if (gvec)
model_instance_find_world_dir(gvec, &tp->turret_norm, model_instance_num, tp->subobj_num, &objp->orient);
model_instance_find_world_dir(gvec, &tp->turret_norm, model_instance_num, tp->subobj_num, &objp->orient, true);
}
void turret_ai_update_aim(ai_info *aip, object *En_Objp, ship_subsys *ss);
@@ -1317,7 +1252,7 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
} else {
if ((lep->type == OBJ_SHIP) && (Ship_info[Ships[lep->instance].ship_info_index].is_big_or_huge())) {
// the turret norm here is from the perspective of the base submodel, not the gun submodel
model_instance_find_world_dir(&turret_norm, &tp->turret_norm, pm, pmi, tp->subobj_num, &objp->orient);
model_instance_find_world_dir(&turret_norm, &tp->turret_norm, pm, pmi, pm->submodel[tp->subobj_num].parent, &objp->orient);
ai_big_pick_attack_point_turret(lep, ssp, &tmp_pos, &turret_norm, &enemy_point, MIN(wip->max_speed * wip->lifetime, wip->weapon_range), tp->turret_fov);
}
else {
@@ -1448,18 +1383,13 @@ int aifft_rotate_turret(object *objp, ship *shipp, ship_subsys *ss, object *lep,
in_fov = turret_fov_test(ss, gvec, &v2e);
if (ss->flags[Ship::Subsystem_Flags::FOV_edge_check]) {
if (in_fov == false)
in_fov = is_object_radius_in_turret_fov(&Objects[ss->turret_enemy_objnum], ss, gvec, &gun_pos, &v2e, predicted_enemy_pos, 0.0f);
}
if (in_fov) {
ret_val = model_rotate_gun(objp, pm, pmi, tp, predicted_enemy_pos);
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos);
} else if ((tp->flags[Model::Subsystem_Flags::Turret_reset_idle]) &&(timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(objp, pm, pmi, tp, predicted_enemy_pos, true);
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos, true);
}
} else if ((ss->system_info->flags[Model::Subsystem_Flags::Turret_reset_idle]) && (timestamp_elapsed(ss->rotation_timestamp))) {
ret_val = model_rotate_gun(objp, pm, pmi, ss->system_info, predicted_enemy_pos, true);
ret_val = model_rotate_gun(objp, pm, pmi, ss, predicted_enemy_pos, true);
}
// by default "ret_val" should be set to 1 for multi-part turrets, and 0 for single-part turrets
@@ -1491,7 +1421,7 @@ float aifft_compute_turret_dot(object *objp, object *enemy_objp, vec3d *abs_gunp
if (ship_subsystem_in_sight(enemy_objp, enemy_subsysp, abs_gunposp, &subobj_pos, 1, &dot_out, &vector_out)) {
vec3d turret_norm;
model_instance_find_world_dir(&turret_norm, &turret_subsysp->system_info->turret_norm, Ships[objp->instance].model_instance_num, turret_subsysp->system_info->subobj_num, &objp->orient);
model_instance_find_world_dir(&turret_norm, &turret_subsysp->system_info->turret_norm, Ships[objp->instance].model_instance_num, turret_subsysp->system_info->subobj_num, &objp->orient, true);
float dot_return = vm_vec_dot(&turret_norm, &vector_out);
if (Ai_info[Ships[objp->instance].ai_index].ai_profile_flags[AI::Profile_Flags::Smart_subsystem_targeting_for_turrets]) {
@@ -2812,25 +2742,20 @@ bool turret_adv_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mo
model_subsystem *tp = ss->system_info;
float dot = vm_vec_dot(v2e, gvec);
if (((dot + size_mod) >= tp->turret_fov) && ((dot - size_mod) <= tp->turret_max_fov)) {
// Since we no longer maintain world_to_turret_matrix, regenerate it here.
object *objp = &Objects[ss->parent_objnum];
vec3d turret_norm;
matrix turret_matrix, world_to_turret_matrix;
model_instance_find_world_dir(&turret_norm, &tp->turret_norm, Ships[objp->instance].model_instance_num, tp->subobj_num, &vmd_identity_matrix);
vm_vector_2_matrix(&turret_matrix, &turret_norm, nullptr, nullptr);
vm_matrix_x_matrix(&world_to_turret_matrix, &objp->orient, &turret_matrix);
object* objp = &Objects[ss->parent_objnum];
matrix turret_matrix;
turret_instance_find_world_orient(&turret_matrix, Ships[objp->instance].model_instance_num, tp->subobj_num, &objp->orient);
vec3d of_dst;
vm_vec_rotate( &of_dst, v2e, &world_to_turret_matrix );
if ((of_dst.xyz.x == 0) && (of_dst.xyz.y == 0)) {
return true;
} else {
of_dst.xyz.z = 0;
vm_vec_rotate(&of_dst, v2e, &turret_matrix);
if ((of_dst.xyz.x == 0) && (of_dst.xyz.z == 0))
return true;
else {
of_dst.xyz.y = 0;
if (!IS_VEC_NULL_SQ_SAFE(&of_dst)) {
vm_vec_normalize(&of_dst);
// now we have 2d vector with lenght of 1 that points at the targets direction after being rotated to turrets FOR
if ((-of_dst.xyz.y + size_mod) >= tp->turret_y_fov)
if ((of_dst.xyz.z + size_mod) >= tp->turret_base_fov)
return true;
}
}
@@ -2841,7 +2766,7 @@ bool turret_adv_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mo
bool turret_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod)
{
bool in_fov = false;
if (ss->system_info->flags[Model::Subsystem_Flags::Turret_alt_math])
if (ss->system_info->flags[Model::Subsystem_Flags::Turret_restricted_fov])
in_fov = turret_adv_fov_test(ss, gvec, v2e, size_mod);
else
in_fov = turret_std_fov_test(ss, gvec, v2e, size_mod);
+5 -3
View File
@@ -866,6 +866,7 @@ static int cfget_cfile_block()
cfile->data = nullptr;
cfile->fp = nullptr;
cfile->type = CFILE_BLOCK_USED;
cf_clear_compression_info(cfile);
return i;
}
}
@@ -921,7 +922,7 @@ int cfclose( CFILE * cfile )
} else {
// VP do nothing
}
cf_clear_compression_info(cfile);
cfile->type = CFILE_BLOCK_UNUSED;
return result;
}
@@ -973,7 +974,7 @@ static CFILE *cf_open_fill_cfblock(const char* source, int line, const char* ori
if(pos == -1L)
pos = 0;
cf_init_lowlevel_read_code(cfp,0,filelength(fileno(fp)), 0 );
cf_check_compression(cfp);
return cfp;
}
}
@@ -1008,7 +1009,7 @@ static CFILE *cf_open_packed_cfblock(const char* source, int line, const char* o
cfp->line_num = line;
cf_init_lowlevel_read_code(cfp,offset, size, 0 );
cf_check_compression(cfp);
return cfp;
}
@@ -1052,6 +1053,7 @@ static CFILE *cf_open_mapped_fill_cfblock(const char* source, int line, const ch
cfp->line_num = line;
cf_init_lowlevel_read_code(cfp, 0, 0, 0 );
#if defined _WIN32
cfp->hMapFile = CreateFileMapping(cfp->hInFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (cfp->hMapFile == NULL) {
+47 -8
View File
@@ -24,6 +24,7 @@
#include "cfile/cfile.h"
#include "cfile/cfilearchive.h"
#include "cfile/cfilecompression.h"
#include "luaconf.h"
#include <sstream>
@@ -33,7 +34,6 @@
#define CHECK_POSITION
// Called once to setup the low-level reading code.
void cf_init_lowlevel_read_code( CFILE * cfile, size_t lib_offset, size_t size, size_t pos )
{
Assert(cfile != nullptr);
@@ -54,6 +54,33 @@ void cf_init_lowlevel_read_code( CFILE * cfile, size_t lib_offset, size_t size,
}
}
//This function checks the file header to see if the file is compressed, if so it fills the correct compression info.
void cf_check_compression(CFILE* cfile)
{
if (cfile->size <= 16)
return;
int header=cfread_int(cfile);
cfseek(cfile, 0, SEEK_SET);
if (comp_check_header(header) == COMP_HEADER_MATCH)
comp_create_ci(cfile, header);
}
//This function is called to cleanup compression info when the cfile handle is reused.
void cf_clear_compression_info(CFILE* cfile)
{
if (cfile->compression_info.header != 0)
{
free(cfile->compression_info.offsets);
free(cfile->compression_info.decoder_buffer);
cfile->compression_info.offsets = nullptr;
cfile->compression_info.decoder_buffer = nullptr;
cfile->compression_info.header = 0;
cfile->compression_info.block_size = 0;
cfile->compression_info.last_decoded_block_pos = 0;
cfile->compression_info.last_decoded_block_bytes = 0;
cfile->compression_info.num_offsets = 0;
}
}
// cfeof() Tests for end-of-file on a stream
@@ -61,11 +88,11 @@ void cf_init_lowlevel_read_code( CFILE * cfile, size_t lib_offset, size_t size,
// returns a nonzero value after the first read operation that attempts to read
// past the end of the file. It returns 0 if the current position is not end of file.
// There is no error return.
int cfeof(CFILE *cfile)
{
Assert(cfile != NULL);
if (cfile->compression_info.header != 0)
return comp_feof(cfile);
int result = 0;
#if defined(CHECK_POSITION) && !defined(NDEBUG)
@@ -92,6 +119,8 @@ int cfeof(CFILE *cfile)
int cftell( CFILE * cfile )
{
Assert(cfile != NULL);
if (cfile->compression_info.header != 0)
return (int)comp_ftell(cfile);
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cfile->fp) {
@@ -117,6 +146,9 @@ int cfseek( CFILE *cfile, int offset, int where )
Assert(cfile != NULL);
if (cfile->compression_info.header != 0)
return comp_fseek(cfile, offset, where);
// TODO: seek to offset in memory mapped file
Assert( !cfile->mem_mapped );
@@ -202,23 +234,31 @@ int cfread(void *buf, int elsize, int nelem, CFILE *cfile)
// This is a file from memory
bytes_read = size;
memcpy(buf, reinterpret_cast<const char*>(cfile->data) + cfile->raw_position, size);
} else if (cfile->compression_info.header != 0) {
bytes_read = comp_fread(cfile, reinterpret_cast<char*>(buf),size);
if (bytes_read != size)
{
mprintf(("\nFile: %s decompression error. Result was: %d expected: %d\n", cfile->original_filename.c_str(), (int)bytes_read, (int)size));
Assertion(bytes_read == size, "File decompression error!");
}
} else {
bytes_read = fread( buf, 1, size, cfile->fp );
bytes_read = fread(buf, 1, size, cfile->fp);
}
if ( bytes_read > 0 ) {
cfile->raw_position += bytes_read;
Assertion(cfile->raw_position <= cfile->size, "Invalid raw_position value detected!");
}
#if defined(CHECK_POSITION) && !defined(NDEBUG)
if (cfile->fp) {
//Raw position is not the fp position with compressed files
if (cfile->fp && cfile->compression_info.header == 0) {
auto tmp_offset = ftell(cfile->fp) - cfile->lib_offset;
Assert(tmp_offset==cfile->raw_position);
Assert(tmp_offset == cfile->raw_position);
}
#endif
return (int)(bytes_read / elsize);
}
int cfread_lua_number(double *buf, CFILE *cfile)
@@ -266,4 +306,3 @@ int cfread_lua_number(double *buf, CFILE *cfile)
return items_read;
}
+19 -2
View File
@@ -7,7 +7,6 @@
*
*/
#ifndef _CFILEARCHIVE_H
#define _CFILEARCHIVE_H
@@ -23,6 +22,17 @@
#define CFILE_BLOCK_UNUSED 0
#define CFILE_BLOCK_USED 1
struct COMPRESSION_INFO {
int header = 0;
size_t compressed_size = 0;
int block_size = 0;
int num_offsets = 0;
int* offsets = nullptr;
char* decoder_buffer = nullptr;
int last_decoded_block_pos = 0;
int last_decoded_block_bytes = 0;
};
struct CFILE {
int type = CFILE_BLOCK_UNUSED; // CFILE_BLOCK_UNUSED, CFILE_BLOCK_USED
int dir_type; // directory location
@@ -44,12 +54,19 @@ struct CFILE {
SCP_string original_filename;
const char* source_file;
int line_num;
COMPRESSION_INFO compression_info;
};
#define MAX_CFILE_BLOCKS 64
extern std::array<CFILE, MAX_CFILE_BLOCKS> Cfile_block_list;
// Called once to setup the low-level reading code.
void cf_init_lowlevel_read_code( CFILE * cfile, size_t lib_offset, size_t size, size_t pos );
void cf_init_lowlevel_read_code(CFILE* cfile, size_t lib_offset, size_t size, size_t pos);
// This checks if the file is compressed or not, and creates the proper compression info if so.
void cf_check_compression(CFILE* cfile);
// Used to clear compression info data and free dynamic memory used by compression
void cf_clear_compression_info(CFILE* cfile);
#endif
+206
View File
@@ -0,0 +1,206 @@
#define _CFILE_INTERNAL
#include <cstdlib>
#include <cstring>
#include <cstdio>
#ifdef _WIN32
#include <io.h>
#include <direct.h>
#include <windows.h>
#include <winbase.h>
#endif
#include "lz4.h"
#include "cfilecompression.h"
#include "cfilearchive.h"
/*INTERNAL FUNCTIONS*/
/*LZ41*/
void lz41_load_offsets(CFILE* cf);
size_t lz41_stream_random_access(CFILE* cf, char* bytes_out, size_t offset, size_t length);
void lz41_create_ci(CFILE* cf, int header);
/*MISC*/
int fso_fseek(CFILE* cfile, int offset, int where);
/*END OF INTERNAL FUNCTIONS*/
int comp_check_header(int header)
{
if (LZ41_FILE_HEADER == header)
return COMP_HEADER_MATCH;
return COMP_HEADER_MISMATCH;
}
void comp_create_ci(CFILE* cf, int header)
{
//mprintf(("(CI)Compressed File Opened: %s \n", cf->original_filename.c_str()));
if (LZ41_FILE_HEADER == header)
lz41_create_ci(cf, header);
//mprintf(("(CI)Uncompressed FileSize: %d \n", cf->size));
//mprintf(("(CI)Compressed FileSize: %d \n", cf->compression_info.compressed_size));
//mprintf(("(CI)Block Size: %d \n", cf->compression_info.block_size));
}
size_t comp_fread(CFILE* cf, char* buffer, size_t length)
{
/* Check the request to be at least 1 byte */
Assertion(length > 0, "Invalid length requested.");
/* Check that we are not requesting to read beyond end of file */
Assertion(cf->raw_position + length <= cf->size, "Invalid length requested.");
if (LZ41_FILE_HEADER == cf->compression_info.header)
return lz41_stream_random_access(cf, buffer, cf->raw_position, length);
return 0;
}
size_t comp_ftell(CFILE* cf)
{
return cf->raw_position;
}
int comp_feof(CFILE* cf)
{
if (cf->raw_position >= cf->size)
return 1;
else
return 0;
}
int comp_fseek(CFILE* cf, int offset, int where)
{
size_t goal_position;
switch (where) {
case SEEK_SET: goal_position = offset; break;
case SEEK_CUR: goal_position = cf->raw_position + offset; break;
case SEEK_END: goal_position = cf->size + offset; break;
default: return 1;
}
// Make sure we don't seek beyond the end of the file
CAP(goal_position,(size_t)0, cf->size);
cf->raw_position = goal_position;
return 0;
}
//Special fseek for compressed files handled by FSO, only SEEK_SET and SEEK_END is supported.
int fso_fseek(CFILE* cfile, int offset, int where)
{
size_t goal_position;
switch (where) {
case SEEK_SET: goal_position = offset + cfile->lib_offset; break;
case SEEK_END: goal_position = cfile->compression_info.compressed_size + offset + cfile->lib_offset; break;
default: return 0;
}
// Make sure we don't seek beyond the end of the file
CAP(goal_position, cfile->lib_offset, cfile->lib_offset + cfile->compression_info.compressed_size);
int result = 0;
if (cfile->fp)
{
result = fseek(cfile->fp, (long)goal_position, SEEK_SET);
Assertion(goal_position >= cfile->lib_offset, "Invalid offset values detected while seeking! Goal was " SIZE_T_ARG ", lib_offset is " SIZE_T_ARG ".", goal_position, cfile->lib_offset);
}
return result;
}
void lz41_create_ci(CFILE* cf, int header)
{
cf->compression_info.header = header;
cf->compression_info.compressed_size = cf->size;
fso_fseek(cf, (int)sizeof(int)*-3, SEEK_END);
auto fNumoffsets = fread(&cf->compression_info.num_offsets, sizeof(int), 1, cf->fp);
auto fSize = fread(&cf->size, sizeof(int), 1, cf->fp);
auto fBsize = fread(&cf->compression_info.block_size, sizeof(int), 1, cf->fp);
Assertion(cf->compression_info.num_offsets > 0, "Invalid number of offsets, compressed file is possibly in the wrong format or corrupted.");
#if !defined(NDEBUG)
Assertion(cf->size > 4, "Invalid filesize, compressed file is possibly in the wrong format or corrupted.");
Assertion(cf->compression_info.block_size > 16, "Invalid block size, compressed file is possibly in the wrong format or corrupted.");
Assertion(fNumoffsets == 1, "Error while reading the number of offsets, compressed file is possibly in the wrong format or corrupted.");
Assertion(fSize == 1, "Error while reading original filesize, compressed file is possibly in the wrong format or corrupted.");
Assertion(fBsize == 1, "Error while reading block size, compressed file is possibly in the wrong format or corrupted.");
#endif
cf->compression_info.decoder_buffer = (char*)malloc(LZ4_compressBound(cf->compression_info.block_size));
cf->compression_info.last_decoded_block_pos = 0;
cf->compression_info.last_decoded_block_bytes = 0;
lz41_load_offsets(cf);
}
void lz41_load_offsets(CFILE* cf)
{
cf->compression_info.offsets = (int*)malloc(cf->compression_info.num_offsets * sizeof(int));
int block;
int* offsets_ptr = cf->compression_info.offsets;
/* Seek to the first offset position, remember to consider the trailing ints */
fso_fseek(cf, ( ( sizeof(int) * cf->compression_info.num_offsets ) * -1 ) - (sizeof(int)*3 ), SEEK_END);
for (block = 0; block < cf->compression_info.num_offsets; ++block)
{
auto bytes_read = fread(offsets_ptr++, sizeof(int), 1, cf->fp);
Assertion(bytes_read == 1, "Error reading offset list.");
}
}
size_t lz41_stream_random_access(CFILE* cf, char* bytes_out, size_t offset, size_t length)
{
LZ4_streamDecode_t lz4_stream_decode_body;
LZ4_streamDecode_t* lz4_stream_decode = &lz4_stream_decode_body;
/* The blocks (current_block to end_block) contain the data we want */
size_t current_block = offset / cf->compression_info.block_size;
size_t end_block = ((offset + length - 1) / cf->compression_info.block_size) + 1;
size_t written_bytes = 0;
if (cf->compression_info.num_offsets <= (int)end_block)
return (size_t)LZ41_OFFSETS_MISMATCH;
/* Seek to the first block to read, if it matches the cached block, search the next one instead */
if (cf->compression_info.last_decoded_block_pos == cf->compression_info.offsets[current_block] && current_block + 1 <= end_block)
fso_fseek(cf, cf->compression_info.offsets[current_block+1], SEEK_SET);
else
fso_fseek(cf, cf->compression_info.offsets[current_block], SEEK_SET);
offset = offset % cf->compression_info.block_size;
char* cmp_buf = (char*)malloc(LZ4_compressBound(cf->compression_info.block_size));
/* Start decoding */
for (; current_block < end_block; ++current_block)
{
/* Only read and decode if the requested block is not the cached one */
if (cf->compression_info.last_decoded_block_pos != cf->compression_info.offsets[current_block])
{
cf->compression_info.last_decoded_block_pos = cf->compression_info.offsets[current_block];
/* The difference in offsets is the size of the block */
int cmp_bytes = cf->compression_info.offsets[current_block + 1] - cf->compression_info.offsets[current_block];
auto bytes_read = fread(cmp_buf, cmp_bytes, 1, cf->fp);
Assertion(bytes_read == 1, "Error reading from compressed file.");
cf->compression_info.last_decoded_block_bytes = LZ4_decompress_safe_continue(lz4_stream_decode, cmp_buf, cf->compression_info.decoder_buffer, cmp_bytes, cf->compression_info.block_size);
if (cf->compression_info.last_decoded_block_bytes <= 0)
{
free(cmp_buf);
return (size_t)LZ41_DECOMPRESSION_ERROR;
}
}
/* Write out the part of the data we care about from buffer */
size_t block_length = (length < (cf->compression_info.last_decoded_block_bytes - offset) ? length : (cf->compression_info.last_decoded_block_bytes - offset));
memcpy(bytes_out + written_bytes, cf->compression_info.decoder_buffer + offset, (size_t)block_length);
written_bytes += block_length;
offset = 0;
length -= block_length;
}
free(cmp_buf);
return written_bytes;
}
+66
View File
@@ -0,0 +1,66 @@
/*
ShivanSpS - Compressed files support for FSO. Many thanks to ngld, taylor and everyone elsewho helped me in getting this done.
-The file header is a version, this is used to tell FSO how to decompress that file, always use 4 chars to mantain alignment.
-The header ID can be used to add diferent revisions to LZ41 decompression system or to add other compression format supports whiout breaking compatibility.
-The system uses a offset list to record the position of every block in file, this list, along with the number of offsets, original filesize,
and block size, must be written by the compressor app.
-A decoder cache is used to store the last decoded block, this ensures each block is read and decoded only once in sequential reads. This cache
is a little bit bigger than the block size, a higher block size means less overhead added to the file, but it also means a little more ram will
be used during decompression.
-All this dynamic memory is assigned at cfopen() and it is cleared on cfclose().
................................char[4]..........(n ints)...(int)..........(int)..........(int)
-COMPRESSED FILE DATA STUCTURE: HEADER|N BLOCKS|N OFFSETS|NUM_OFFSETS|ORIGINAL_FILESIZE|BLOCK_SIZE
*/
#ifndef _CFILECOMPRESSION_H
#define _CFILECOMPRESSION_H
struct CFILE;
/*LZ41*/
#define LZ41_FILE_HEADER 0x31345A4C // "14ZL" -> "LZ41", inverted
#define LZ41_DECOMPRESSION_ERROR -1
#define LZ41_MAX_BLOCKS_OVERFLOW -2
#define LZ41_HEADER_MISMATCH -3
#define LZ41_OFFSETS_MISMATCH -4
/******/
#define COMP_HEADER_MATCH 1
#define COMP_HEADER_MISMATCH 0
/*
Returns COMP_HEADER_MATCH if header is a valid compressed file header,
returns COMP_HEADER_MISMATCH if it dosent.
*/
int comp_check_header(int header);
/*
This is called to generate the correct compression_info data
after the file has been indentified as a compressed file.
This must be done before calling any other function.
*/
void comp_create_ci(CFILE* cf, int header);
/*
Read X bytes from the uncompressed file starting from X offset.
Returns the amount of bytes read, and 0 or lower to indicate errors.
*/
size_t comp_fread(CFILE* cf, char* buffer, size_t length);
/*
Returns the current uncompressed file position.
*/
size_t comp_ftell(CFILE* cf);
/*
Returns 1 of the uncompressed file has been completely read, otherwise it returns a 0.
*/
int comp_feof(CFILE* cf);
/*
Used to move the uncompressed file current position.
*/
int comp_fseek(CFILE* cf, int offset, int where);
#endif
+8 -1
View File
@@ -246,7 +246,7 @@ Flag exe_params[] =
{ "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", },
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
{ "-benchmark_mode", "Puts the game into benchmark mode", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-benchmark_mode", },
{ "-profile_frame_time","Profile frame time", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_time", },
{ "-profile_frame_time","Profile frame time", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_time", },
{ "-profile_write_file", "Write profiling information to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_write_file", },
{ "-json_profiling", "Generate JSON profiling output", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_profiling", },
{ "-debug_window", "Enable the debug window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-debug_window", },
@@ -479,6 +479,7 @@ cmdline_parm reparse_mainhall_arg("-reparse_mainhall", NULL, AT_NONE); //Cmdline
cmdline_parm frame_profile_write_file("-profile_write_file", NULL, AT_NONE); // Cmdline_profile_write_file
cmdline_parm no_unfocused_pause_arg("-no_unfocused_pause", NULL, AT_NONE); //Cmdline_no_unfocus_pause
cmdline_parm benchmark_mode_arg("-benchmark_mode", NULL, AT_NONE); //Cmdline_benchmark_mode
cmdline_parm pilot_arg("-pilot", nullptr, AT_STRING); //Cmdline_pilot
cmdline_parm noninteractive_arg("-noninteractive", NULL, AT_NONE); //Cmdline_noninteractive
cmdline_parm json_profiling("-json_profiling", NULL, AT_NONE); //Cmdline_json_profiling
cmdline_parm show_video_info("-show_video_info", NULL, AT_NONE); //Cmdline_show_video_info
@@ -510,6 +511,7 @@ int Cmdline_reparse_mainhall = 0;
bool Cmdline_profile_write_file = false;
bool Cmdline_no_unfocus_pause = false;
bool Cmdline_benchmark_mode = false;
const char *Cmdline_pilot = nullptr;
bool Cmdline_noninteractive = false;
bool Cmdline_json_profiling = false;
bool Cmdline_frame_profile = false;
@@ -2123,6 +2125,11 @@ bool SetCmdlineParams()
Cmdline_benchmark_mode = true;
}
if (pilot_arg.found())
{
Cmdline_pilot = pilot_arg.str();
}
if (noninteractive_arg.found())
{
Cmdline_noninteractive = true;
+1
View File
@@ -143,6 +143,7 @@ extern int Cmdline_reparse_mainhall;
extern bool Cmdline_profile_write_file;
extern bool Cmdline_no_unfocus_pause;
extern bool Cmdline_benchmark_mode;
extern const char *Cmdline_pilot;
extern bool Cmdline_noninteractive;
extern bool Cmdline_json_profiling;
extern bool Cmdline_frame_profile;
+1 -1
View File
@@ -1934,7 +1934,7 @@ void control_config_do_frame(float frametime)
for (i=0; i<MOUSE_NUM_BUTTONS; i++) {
if (mouse_down(1 << i)) {
Assert(!(z & JOY_AXIS));
control_config_bind_btn(z, CC_bind(CID_MOUSE, static_cast<short>(i)), 1);
control_config_bind_btn(z, CC_bind(CID_JOY0, static_cast<short>(i)), 1);
strcpy_s(bound_string, Joy_button_text[i]);
done = true;
+14 -13
View File
@@ -424,17 +424,6 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
sip = &Ship_info[shipp->ship_info_index];
vaporize = (shipp->flags[Ship::Ship_Flags::Vaporize]);
if ( !hull_flag ) {
// Make vaporize debris seen from farther away
float dist = vm_vec_dist_quick( pos, &Eye_position );
if (vaporize) {
dist /= 2.0f;
}
if ( dist > source_obj->radius * 20.0f ) {
return NULL;
}
}
// try to maintain our soft limit
if (hull_flag && (Num_hull_pieces >= SOFT_LIMIT_DEBRIS_PIECES)) {
// cause oldest hull debris chunk to blow up
@@ -480,6 +469,18 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
float radius = submodel_get_radius(db->model_num, db->submodel_num);
// if its generic, maybe cull it if its too small and far
if (!hull_flag) {
float dist = vm_vec_dist_quick(pos, &Eye_position);
// Make vaporize debris seen from farther away
if (vaporize) {
dist /= 2.0f;
}
if (dist > radius * 200.0f) {
return nullptr;
}
}
//WMC - We must survive until now, at least.
db->must_survive_until = timestamp();
@@ -560,7 +561,7 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
db->next_fireball = timestamp_rand(500,2000); //start one 1/2 - 2 secs later
if ( pos == NULL )
if ( pos == nullptr )
pos = &source_obj->pos;
flagset<Object::Object_Flags> default_flags;
@@ -579,7 +580,7 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
objnum = obj_create( OBJ_DEBRIS, parent_objnum, n, &orient, pos, radius, default_flags);
if ( objnum == -1 ) {
mprintf(("Couldn't create debris object -- out of object slots\n"));
return NULL;
return nullptr;
}
db->objnum = objnum;
+2 -4
View File
@@ -12,7 +12,7 @@ layout (std140) uniform genericData {
vec3 fog_color;
float fog_start;
float fog_scale;
float fog_density;
float zNear;
float zFar;
};
@@ -31,9 +31,7 @@ void main()
if (isinf(view_depth)) {
fragOut0.rgb = color_in.rgb;
} else {
// This is the same formula that is also used by the main shader
float fog_dist = clamp((view_depth - fog_start) * 0.75 * fog_scale, 0.0, 1.0);
float fog_dist = clamp(1 - pow(fog_density, view_depth - fog_start) , 0.0, 1.0);
vec3 finalFogColor = srgb_to_linear(fog_color);
fragOut0.rgb = mix(color_in.rgb, finalFogColor, fog_dist);
+15 -2
View File
@@ -14,6 +14,7 @@
#include "graphics/tmapper.h"
#include "localization/localize.h"
#include "model/model.h"
#include "nebula/neb.h"
#include "object/object.h"
#include "options/Option.h"
#include "parse/parselo.h"
@@ -286,11 +287,13 @@ static void parse_fireball_tbl(const char *table_filename)
}
}
bool first_time;
// now select our entry accordingly...
// are we using a previous entry?
if (existing_idx >= 0)
{
fi = &Fireball_info[existing_idx];
first_time = false;
}
// we are creating a new entry, so set some defaults
else
@@ -314,6 +317,7 @@ static void parse_fireball_tbl(const char *table_filename)
fireball_set_default_warp_attributes(Num_fireball_types);
Num_fireball_types++;
first_time = true;
}
// copy over what we already parsed
@@ -321,6 +325,7 @@ static void parse_fireball_tbl(const char *table_filename)
strcpy_s(fi->unique_id, unique_id);
strcpy_s(fi->lod[0].filename, fireball_filename);
// Do we have a LOD num?
if (optional_string("$LOD:"))
{
@@ -328,6 +333,9 @@ static void parse_fireball_tbl(const char *table_filename)
if (fi->lod_count > MAX_FIREBALL_LOD)
fi->lod_count = MAX_FIREBALL_LOD;
} else if (first_time) {
//assume a LOD of at least 1
fi->lod_count = 1;
}
// check for particular lighting color
@@ -1037,19 +1045,24 @@ void fireball_render(object* obj, model_draw_list *scene)
if ( fb->current_bitmap < 0 )
return;
float alpha = 1.0f;
if (The_mission.flags[Mission::Mission_Flags::Fullneb] && Neb_affects_fireballs)
alpha *= neb2_get_fog_visibility(&obj->pos, NEB_FOG_VISIBILITY_MULT_FIREBALL(obj->radius));
g3_transfer_vertex(&p, &obj->pos);
switch ( fb->fireball_render_type ) {
case FIREBALL_MEDIUM_EXPLOSION: {
batching_add_volume_bitmap(fb->current_bitmap, &p, fb->orient, obj->radius);
batching_add_volume_bitmap(fb->current_bitmap, &p, fb->orient, obj->radius, alpha);
}
break;
case FIREBALL_LARGE_EXPLOSION: {
// Make the big explosions rotate with the viewer.
batching_add_volume_bitmap_rotated(fb->current_bitmap, &p, (i2fl(fb->orient)*PI) / 180.0f, obj->radius);
batching_add_volume_bitmap_rotated(fb->current_bitmap, &p, (i2fl(fb->orient)*PI) / 180.0f, obj->radius, alpha);
}
break;
+1 -1
View File
@@ -91,7 +91,7 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
g3_transfer_vertex( &verts[4], &vecs[4] );
float alpha = (The_mission.flags[Mission::Mission_Flags::Fullneb]) ? (1.0f - neb2_get_fog_intensity(obj)) : 1.0f;
float alpha = (The_mission.flags[Mission::Mission_Flags::Fullneb]) ? neb2_get_fog_visibility(obj) : 1.0f;
//batch_add_bitmap(warp_glow_bitmap, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT, &verts[4], 0, r, alpha);
batching_add_bitmap(warp_glow_bitmap, &verts[4], 0, r, alpha);
+3 -1
View File
@@ -41,6 +41,7 @@
#include "scripting/scripting.h"
#include "tracing/tracing.h"
#include "utils/boost/hash_combine.h"
#include "gamesequence/gamesequence.h"
#ifdef WITH_OPENGL
#include "graphics/opengl/gropengl.h"
@@ -2547,7 +2548,8 @@ void gr_flip(bool execute_scripting)
executor::OnFrameExecutor->process();
// m!m avoid running CHA_ONFRAME when the "Quit mission" popup is shown. See mantis 2446 for reference
if (execute_scripting && !popup_active()) {
// Cyborg - A similar bug will occur when a mission is restarted so check for that, too.
if (execute_scripting && !popup_active() && GameState_Stack_Valid() && !((gameseq_get_state() == GS_STATE_GAME_PLAY) && !(Game_mode & GM_IN_MISSION))) {
TRACE_SCOPE(tracing::LuaOnFrame);
// WMC - Do conditional hooks. Yippee!
+3 -3
View File
@@ -301,8 +301,8 @@ void gr_opengl_deferred_lighting_finish()
GL_state.Texture.Enable(0, GL_TEXTURE_2D, Scene_emissive_texture);
GL_state.Texture.Enable(1, GL_TEXTURE_2D, Scene_depth_texture);
float fog_near, fog_far;
neb2_get_adjusted_fog_values(&fog_near, &fog_far, nullptr);
float fog_near, fog_far, fog_density;
neb2_get_adjusted_fog_values(&fog_near, &fog_far, &fog_density);
unsigned char r, g, b;
neb2_get_fog_color(&r, &g, &b);
@@ -311,7 +311,7 @@ void gr_opengl_deferred_lighting_finish()
opengl_set_generic_uniform_data<graphics::generic_data::fog_data>([&](graphics::generic_data::fog_data* data) {
data->fog_start = fog_near;
data->fog_scale = 1.0f / (fog_far - fog_near);
data->fog_density = fog_density;
data->fog_color.xyz.x = r / 255.f;
data->fog_color.xyz.y = g / 255.f;
data->fog_color.xyz.z = b / 255.f;
+1 -1
View File
@@ -284,7 +284,7 @@ struct fog_data {
vec3d fog_color;
float fog_start;
float fog_scale;
float fog_density;
float zNear;
float zFar;
+5 -5
View File
@@ -236,7 +236,7 @@ void HudGaugeReticle::initBitmaps(char *fname)
{
crosshair.first_frame = bm_load_animation(fname, &crosshair.num_frames);
if (crosshair.first_frame < 0) {
mprintf(("Cannot load hud ani: %s\n", fname));
Warning(LOCATION, "Cannot load hud ani: %s\n", fname);
}
}
@@ -495,7 +495,7 @@ void HudGaugeThrottle::initBitmaps(char *fname)
throttle_frames.first_frame = bm_load_animation(fname, &throttle_frames.num_frames);
if (throttle_frames.first_frame < 0) {
mprintf(("Cannot load hud ani: %s\n", fname));
Warning(LOCATION, "Cannot load hud ani: %s\n", fname);
}
}
@@ -748,17 +748,17 @@ void HudGaugeThreatIndicator::initBitmaps(char *fname_arc, char *fname_laser, ch
{
threat_arc.first_frame = bm_load_animation(fname_arc, &threat_arc.num_frames);
if (threat_arc.first_frame < 0) {
mprintf(("Cannot load hud ani: %s\n", fname_arc));
Warning(LOCATION, "Cannot load hud ani: %s\n", fname_arc);
}
laser_warn.first_frame = bm_load_animation(fname_laser, &laser_warn.num_frames);
if (laser_warn.first_frame < 0) {
mprintf(("Cannot load hud ani: %s\n", fname_laser));
Warning(LOCATION, "Cannot load hud ani: %s\n", fname_laser);
}
lock_warn.first_frame = bm_load_animation(fname_lock, &lock_warn.num_frames);
if (lock_warn.first_frame < 0) {
mprintf(("Cannot load hud ani: %s\n", fname_lock));
Warning(LOCATION, "Cannot load hud ani: %s\n", fname_lock);
}
}
-9
View File
@@ -692,15 +692,6 @@ void process_debug_keys(int k)
case KEY_DEBUGGED + KEY_H:
hud_target_toggle_hidden_from_sensors();
break;
case KEY_DEBUGGED + KEY_F:
extern int wacky_scheme;
if(wacky_scheme == 3){
wacky_scheme = 0;
} else {
wacky_scheme++;
}
break;
case KEY_DEBUGGED + KEY_ALTED + KEY_F:
Framerate_delay += 10;
+12 -1
View File
@@ -308,11 +308,22 @@ void LabRenderer::useBackground(const SCP_string& mission_name) {
gr_set_ambient_light(ambient_light_level & 0xff, (ambient_light_level >> 8) & 0xff,
(ambient_light_level >> 16) & 0xff);
strcpy_s(Neb2_texture_name, "Eraseme3");
strcpy_s(Neb2_texture_name, "");
Neb2_poof_flags = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5));
bool nebula = false;
if (optional_string("+Neb2:")) {
nebula = true;
stuff_string(Neb2_texture_name, F_NAME, MAX_FILENAME_LEN);
} else if (optional_string("+Neb2Color:")) {
nebula = true;
int neb_colors[3];
stuff_int_list(neb_colors, 3, RAW_INTEGER_TYPE);
Neb2_fog_color[0] = (ubyte)neb_colors[0];
Neb2_fog_color[1] = (ubyte)neb_colors[1];
Neb2_fog_color[2] = (ubyte)neb_colors[2];
}
if (nebula){
required_string("+Neb2Flags:");
stuff_int(&Neb2_poof_flags);
+11 -1
View File
@@ -955,8 +955,18 @@ const char *XSTR(const char *str, int index, bool force_lookup)
// return translation of string
if (Xstr_table[index].str)
return Xstr_table[index].str;
#ifndef NDEBUG
else
mprintf(("No XSTR entry in strings.tbl for index %d\n", index));
{
// make sure missing strings are only logged once
static SCP_unordered_set<int> Warned_xstr_indexes;
if (Warned_xstr_indexes.count(index) == 0)
{
Warned_xstr_indexes.insert(index);
mprintf(("No XSTR entry in strings.tbl for index %d\n", index));
}
}
#endif
}
}
+7 -1
View File
@@ -413,6 +413,12 @@ void player_select_do()
gr_set_bitmap(Player_select_background_bitmap);
gr_bitmap(0,0,GR_RESIZE_MENU);
//skip this if pilot is given through cmdline, assuming single-player
if (Cmdline_pilot) {
player_finish_select(Cmdline_pilot, false);
return;
}
// press the accept button
if (Player_select_autoaccept) {
Player_select_buttons[gr_screen.res][ACCEPT_BUTTON].button.press_button();
@@ -1444,7 +1450,7 @@ void player_finish_select(const char* callsign, bool is_multi) {
// now read in a the pilot data
if ( !Pilot.load_player(callsign, Player) ) {
Error(LOCATION,"Couldn't load pilot file, bailing");
Error(LOCATION,"Couldn't load pilot file for pilot \"%s\", bailing", callsign);
Player = nullptr;
} else {
// NOTE: this may fail if there is no current campaign, it's not fatal
+2 -1
View File
@@ -25,13 +25,14 @@ namespace Mission {
Red_alert, // a red-alert mission - Goober5000
Scramble, // a scramble mission - Goober5000
No_builtin_command, // turns off Command without turning off pilots - Karajorma
Player_start_ai, // Player Starts mission under AI Control (NOT MULTI COMPATABLE) - Kazan
Player_start_ai, // Player starts mission under AI Control (NOT MULTI COMPATABLE) - Kazan
All_attack, // all teams at war - Goober5000
Use_ap_cinematics, // use autopilot cinematics - Kazan
Deactivate_ap, // deactivate autopilot - KeldorKatarn (patch approved by Kazan)
Always_show_goals, // Show the mission goals, even for training missions - Karajorma
End_to_mainhall, // Return to the mainhall after debrief - niffiwan
Override_hashcommand, // Override #Command with the Command info in Mission Specs - Goober5000
Player_start_chase_view, // Player starts mission in chase view - Goober5000
NUM_VALUES
};
+26 -20
View File
@@ -4236,9 +4236,13 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, int force, int spec
// also, if multiplayer, set the parse object's net signature to be wing's net signature
// base + total_arrived_count (before adding 1)
if (Game_mode & GM_MULTIPLAYER)
// Cyborg -- The original ships in the wave have their net_signature set at mission parse
// so only do this if this is a subsequent wave.
if (Game_mode & GM_MULTIPLAYER && wingp->num_waves > 1)
{
p_objp->net_signature = (ushort) (wingp->net_signature + wingp->total_arrived_count);
// Cyborg -- Also, then we need to subtract the original wave's number of fighters
// and also subtract 1 to use the wing's starting signature
p_objp->net_signature = (ushort) (wingp->net_signature + wingp->total_arrived_count - (wingp->wave_count + 1));
}
@@ -4683,7 +4687,8 @@ void parse_wing(mission *pm)
int next_signature;
wingp->net_signature = multi_assign_network_signature( MULTI_SIG_SHIP );
next_signature = wingp->net_signature + (wingp->wave_count * wingp->num_waves);
// Cyborg -- Subtract one because the original wave already has its signatures set.
next_signature = wingp->net_signature + (wingp->wave_count * (wingp->num_waves - 1));
if ( next_signature > SHIP_SIG_MAX )
Error(LOCATION, "Too many total ships in mission (%d) for network signature assignment", SHIP_SIG_MAX);
multi_set_network_signature( (ushort)next_signature, MULTI_SIG_SHIP );
@@ -5060,6 +5065,9 @@ void parse_event(mission * /*pm*/)
}
}
// Need to set this to zero so that we don't accidentally reuse old data.
event->flags = 0;
if (optional_string("+Event Flags:")) {
parse_string_flag_list(&event->flags, Mission_event_flags, Num_mission_event_flags);
}
@@ -5480,11 +5488,21 @@ void parse_bitmaps(mission *pm)
Mission_palette = 1;
// neb2 info
strcpy_s(Neb2_texture_name, "Eraseme3");
strcpy_s(Neb2_texture_name, "");
Neb2_poof_flags = ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5));
if(optional_string("+Neb2:")){
bool nebula = false;
if (optional_string("+Neb2:")) {
nebula = true;
stuff_string(Neb2_texture_name, F_NAME, MAX_FILENAME_LEN);
} else if (optional_string("+Neb2Color:")) {
nebula = true;
int neb_colors[3];
stuff_int_list(neb_colors, 3, RAW_INTEGER_TYPE);
Neb2_fog_color[0] = (ubyte)neb_colors[0];
Neb2_fog_color[1] = (ubyte)neb_colors[1];
Neb2_fog_color[2] = (ubyte)neb_colors[2];
}
if (nebula) {
required_string("+Neb2Flags:");
stuff_int(&Neb2_poof_flags);
@@ -8159,20 +8177,8 @@ void mission_process_alt_types()
// truncate at a single hash
end_string_at_first_hash_symbol(Mission_alt_types[i], true);
// consolidate double hashes
auto src = Mission_alt_types[i];
auto dest = src;
while (*src)
{
if (*src == '#' && *(src + 1) == '#')
dest--;
++src;
++dest;
if (src != dest)
*dest = *src;
}
// ## -> #
consolidate_double_characters(Mission_alt_types[i], '#');
}
}
+24
View File
@@ -66,6 +66,10 @@ bool Chase_view_default;
SCP_vector<gr_capability> Required_render_ext;
float Weapon_SS_Threshold_Turret_Inaccuracy;
bool Render_player_mflash;
bool Neb_affects_beams;
bool Neb_affects_weapons;
bool Neb_affects_particles;
bool Neb_affects_fireballs;
SCP_vector<std::pair<SCP_string, gr_capability>> req_render_ext_pairs = {
std::make_pair("BPTC Texture Compression", CAPABILITY_BPTC)
@@ -377,6 +381,22 @@ void parse_mod_table(const char *filename)
stuff_boolean(&Render_player_mflash);
}
if (optional_string("$Beams affected by nebula visibility:")) {
stuff_boolean(&Neb_affects_beams);
}
if (optional_string("$Weapons affected by nebula visibility:")) {
stuff_boolean(&Neb_affects_weapons);
}
if (optional_string("$Particles affected by nebula visibility:")) {
stuff_boolean(&Neb_affects_particles);
}
if (optional_string("$Fireballs affected by nebula visibility:")) {
stuff_boolean(&Neb_affects_fireballs);
}
optional_string("#NETWORK SETTINGS");
if (optional_string("$FS2NetD port:")) {
@@ -664,4 +684,8 @@ void mod_table_reset()
Required_render_ext.clear();
Weapon_SS_Threshold_Turret_Inaccuracy = 0.7f; // Defaults to retail value of 0.7 --wookieejedi
Render_player_mflash = false;
Neb_affects_beams = false;
Neb_affects_weapons = false;
Neb_affects_particles = false;
Neb_affects_fireballs = false;
}
+4
View File
@@ -58,6 +58,10 @@ extern bool Framerate_independent_turning;
extern bool Ai_respect_tabled_turntime_rotdamp;
extern bool Chase_view_default;
extern bool Render_player_mflash;
extern bool Neb_affects_beams;
extern bool Neb_affects_weapons;
extern bool Neb_affects_particles;
extern bool Neb_affects_fireballs;
void mod_table_init();
+3 -3
View File
@@ -159,7 +159,7 @@ public:
vec3d turret_norm; // direction this turret faces (i.e. the normal to the turret base, or the center of the field of view)
float turret_fov; // dot of turret_norm:vec_to_enemy > this means can see
float turret_max_fov; // dot of turret_norm:vec_to_enemy <= this means barrels can elevate up to the target
float turret_y_fov; // turret's base's fov
float turret_base_fov; // turret's base's fov
int turret_num_firing_points; // number of firing points on this turret
vec3d turret_firing_point[MAX_TFP]; // in parent object's reference frame, point from which to fire.
int turret_gun_sobj; // Which subobject in this model the firing points are linked to.
@@ -914,7 +914,7 @@ extern int modelstats_num_sortnorms;
#endif
// Tries to move joints so that the turret points to the point dst.
extern int model_rotate_gun(object *objp, polymodel *pm, polymodel_instance *pmi, model_subsystem *turret, vec3d *dst, bool reset = false);
extern int model_rotate_gun(object *objp, polymodel *pm, polymodel_instance *pmi, ship_subsys *ss, vec3d *dst, bool reset = false);
// Rotates the angle of a submodel. Use this so the right unlocked axis
// gets stuffed.
@@ -962,7 +962,7 @@ void model_init_submodel_axis_pt(polymodel *pm, polymodel_instance *pmi, int sub
// return the point in 3-space in outpnt.
extern void model_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_num, int submodel_num, const matrix *objorient);
extern void model_find_world_dir(vec3d *out_dir, const vec3d *in_dir, const polymodel *pm, int submodel_num, const matrix *objorient);
extern void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient);
extern void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient, bool use_submodel_parent = false);
extern void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, const polymodel *pm, const polymodel_instance *pmi, int submodel_num, const matrix *objorient);
// Clears all the submodel instances stored in a model to their defaults.
+1 -1
View File
@@ -23,7 +23,7 @@ namespace Model {
Fire_on_target, // prevents turret from firing unless it is pointing at the firingpoints are pointing at the target
No_ss_targeting, // toggles the subsystem targeting for the turret
Turret_reset_idle, // makes turret reset to their initial position if the target is out of field of view
Turret_alt_math, // tells the game to use additional calculations should turret have a defined y fov
Turret_restricted_fov, // tells the game to use additional calculations should turret have a limited base fov or elevation
Dum_rotates, // Bobboau
Carry_shockwave, // subsystem - even with 'carry no damage' flag - will carry shockwave damage to the hull
Allow_landing, // This subsystem can be landed on
+6 -7
View File
@@ -3727,10 +3727,9 @@ void submodel_rotate(bsp_info *sm, submodel_instance *smi)
// Tries to move joints so that the turret points to the point dst.
// turret1 is the angles of the turret, turret2 is the angles of the gun from turret
// Returns 1 if rotated gun, 0 if no gun to rotate (rotation handled by AI)
int model_rotate_gun(object *objp, polymodel *pm, polymodel_instance *pmi, model_subsystem *turret, vec3d *dst, bool reset)
int model_rotate_gun(object *objp, polymodel *pm, polymodel_instance *pmi, ship_subsys *ss, vec3d *dst, bool reset)
{
ship *shipp = &Ships[objp->instance];
ship_subsys *ss = ship_get_subsys(shipp, turret->subobj_name);
model_subsystem *turret = ss->system_info;
// This should not happen
if ( turret->turret_gun_sobj < 0 || turret->subobj_num == turret->turret_gun_sobj ) {
@@ -3813,7 +3812,7 @@ int model_rotate_gun(object *objp, polymodel *pm, polymodel_instance *pmi, model
}
}
if (turret->flags[Model::Subsystem_Flags::Turret_alt_math])
if (turret->flags[Model::Subsystem_Flags::Turret_restricted_fov])
limited_base_rotation = true;
//------------
@@ -4237,11 +4236,11 @@ void model_find_world_dir(vec3d *out_dir, const vec3d *in_dir, const polymodel *
}
// the same as model_find_world_dir - just taking model instance data into account
void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient)
void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, int model_instance_num, int submodel_num, const matrix *objorient, bool use_submodel_parent)
{
auto pmi = model_get_instance(model_instance_num);
auto pm = model_get(pmi->model_num);
model_instance_find_world_dir(out_dir, in_dir, pm, pmi, submodel_num, objorient);
model_instance_find_world_dir(out_dir, in_dir, pm, pmi, use_submodel_parent ? pm->submodel[submodel_num].parent : submodel_num, objorient);
}
void model_instance_find_world_dir(vec3d *out_dir, const vec3d *in_dir, const polymodel *pm, const polymodel_instance *pmi, int submodel_num, const matrix *objorient)
@@ -5370,7 +5369,7 @@ void model_subsystem::reset()
turret_fov = 0;
turret_max_fov = 0;
turret_y_fov = 0;
turret_base_fov = 0;
turret_num_firing_points = 0;
for (auto it = std::begin(turret_firing_point); it != std::end(turret_firing_point); ++it)
it->xyz.x = it->xyz.y = it->xyz.z = 0.0f;
+4 -4
View File
@@ -1572,7 +1572,7 @@ void submodel_render_queue(model_render_params *render_info, model_draw_list *sc
if (objnum >= 0)
obj = &Objects[objnum];
neb2_get_adjusted_fog_values(&fog_near, &fog_far, obj);
neb2_get_adjusted_fog_values(&fog_near, &fog_far, nullptr, obj);
unsigned char r, g, b;
neb2_get_fog_color(&r, &g, &b);
@@ -1685,7 +1685,7 @@ void model_render_glowpoint(int point_num, vec3d *pos, matrix *orient, glow_poin
//vec3d npnt;
//vm_vec_add(&npnt, &loc_offset, pos);
d *= (1.0f - neb2_get_fog_intensity(&world_pnt));
d *= neb2_get_fog_visibility(&world_pnt, NEB_FOG_VISIBILITY_MULT_GLOWPOINT);
w *= 1.5; //make it bigger in a nebula
}
@@ -2145,7 +2145,7 @@ void model_queue_render_thrusters(model_render_params *interp, polymodel *pm, in
vm_vec_unrotate(&npnt, &gpt->pnt, orient);
vm_vec_add2(&npnt, pos);
fog_int = (1.0f - (neb2_get_fog_intensity(&npnt)));
fog_int = neb2_get_fog_visibility(&npnt, NEB_FOG_VISIBILITY_MULT_THRUSTER);
if (fog_int > 1.0f)
fog_int = 1.0f;
@@ -2645,7 +2645,7 @@ void model_render_queue(model_render_params* interp, model_draw_list* scene, int
// if we're in nebula mode, fog everything except for the warp holes and other non-fogged models
if ( (The_mission.flags[Mission::Mission_Flags::Fullneb]) && (Neb2_render_mode != NEB2_RENDER_NONE) && !(model_flags & MR_NO_FOGGING) ) {
float fog_near = 10.0f, fog_far = 1000.0f;
neb2_get_adjusted_fog_values(&fog_near, &fog_far, objp);
neb2_get_adjusted_fog_values(&fog_near, &fog_far, nullptr, objp);
unsigned char r, g, b;
neb2_get_fog_color(&r, &g, &b);
+48 -88
View File
@@ -35,9 +35,7 @@
bool Nebula_sexp_used = false;
static ubyte Neb2_fog_color_r = 0;
static ubyte Neb2_fog_color_g = 0;
static ubyte Neb2_fog_color_b = 0;
ubyte Neb2_fog_color[3] = { 0,0,0 };
static ubyte *Neb2_htl_fog_data = NULL;
@@ -159,6 +157,10 @@ float Neb2_awacs = -1.0f;
float Neb2_fog_near_mult = 1.0f;
float Neb2_fog_far_mult = 1.0f;
// this is the percent of visibility at the fog far distance
const float NEB_FOG_FAR_PCT = 0.1f;
// how many "slices" are in the current player nebuls
int Neb2_slices = 5;
@@ -168,8 +170,7 @@ neb2_detail Neb2_detail[MAX_DETAIL_LEVEL] = {
{ // lowest detail level
0.575f, // max alpha for this detail level in Glide
0.71f, // max alpha for this detail level in D3d
0.13f, // break alpha (below which, poofs don't draw). this affects the speed and visual quality a lot
150.0f, 150.0f / 1.3333f, // x and y alpha fade/break values. adjust alpha on the polys as they move offscreen
0.013f, // break alpha (below which, poofs don't draw). this affects the speed and visual quality a lot
510.0f, // total dimension of player poof cube
50.0f, // inner radius of the player poof cube
250.0f, // outer radius of the player pood cube
@@ -179,8 +180,7 @@ neb2_detail Neb2_detail[MAX_DETAIL_LEVEL] = {
{ // 2nd lowest detail level
0.575f, // max alpha for this detail level in Glide
0.71f, // max alpha for this detail level in D3d
0.125f, // break alpha (below which, poofs don't draw). this affects the speed and visual quality a lot
300.0f, 300.0f / 1.3333f, // x and y alpha fade/break values. adjust alpha on the polys as they move offscreen
0.0125f, // break alpha (below which, poofs don't draw). this affects the speed and visual quality a lot
550.0f, // total dimension of player poof cube
100.0f, // inner radius of the player poof cube
250.0f, // outer radius of the player pood cube
@@ -190,8 +190,7 @@ neb2_detail Neb2_detail[MAX_DETAIL_LEVEL] = {
{ // 2nd highest detail level
0.575f, // max alpha for this detail level in Glide
0.71f, // max alpha for this detail level in D3d
0.1f, // break alpha (below which, poofs don't draw). this affects the speed and visual quality a lot
300.0f, 300.0f / 1.3333f, // x and y alpha fade/break values. adjust alpha on the polys as they move offscreen
0.01f, // break alpha (below which, poofs don't draw). this affects the speed and visual quality a lot
550.0f, // total dimension of player poof cube
150.0f, // inner radius of the player poof cube
250.0f, // outer radius of the player pood cube
@@ -201,8 +200,7 @@ neb2_detail Neb2_detail[MAX_DETAIL_LEVEL] = {
{ // higest detail level
0.475f, // max alpha for this detail level in Glide
0.575f, // max alpha for this detail level in D3d
0.05f, // break alpha (below which, poofs don't draw). this affects the speed and visual quality a lot
200.0f, 200.0f / 1.3333f, // x and y alpha fade/break values. adjust alpha on the polys as they move offscreen
0.005f, // break alpha (below which, poofs don't draw). this affects the speed and visual quality a lot
750.0f, // total dimension of player poof cube
200.0f, // inner radius of the player poof cube
360.0f, // outer radius of the player pood cube
@@ -339,9 +337,9 @@ void neb2_set_detail_level(int level)
void neb2_get_fog_color(ubyte *r, ubyte *g, ubyte *b)
{
if (r) *r = Neb2_fog_color_r;
if (g) *g = Neb2_fog_color_g;
if (b) *b = Neb2_fog_color_b;
if (r) *r = Neb2_fog_color[0];
if (g) *g = Neb2_fog_color[1];
if (b) *b = Neb2_fog_color[2];
}
void neb2_level_init()
@@ -373,13 +371,13 @@ void neb2_post_level_init()
return;
}
// Set a default colour just in case something goes wrong
Neb2_fog_color_r = 30;
Neb2_fog_color_g = 52;
Neb2_fog_color_b = 157;
// OK, lets try something a bit more interesting
if (strlen(Neb2_texture_name)) {
// Set a default colour just in case something goes wrong
Neb2_fog_color[0] = 30;
Neb2_fog_color[1] = 52;
Neb2_fog_color[2] = 157;
Neb2_htl_fog_data = new ubyte[768];
if ((Neb2_htl_fog_data != NULL) && (pcx_read_header(Neb2_texture_name, NULL, NULL, NULL, NULL, Neb2_htl_fog_data) == PCX_ERROR_NONE)) {
@@ -395,12 +393,12 @@ void neb2_post_level_init()
}
if (pcount > 0) {
Neb2_fog_color_r = (ubyte)(r / pcount);
Neb2_fog_color_g = (ubyte)(g / pcount);
Neb2_fog_color_b = (ubyte)(b / pcount);
Neb2_fog_color[0] = (ubyte)(r / pcount);
Neb2_fog_color[1] = (ubyte)(g / pcount);
Neb2_fog_color[2] = (ubyte)(b / pcount);
} else {
// it's just black
Neb2_fog_color_r = Neb2_fog_color_g = Neb2_fog_color_b = 0;
Neb2_fog_color[0] = Neb2_fog_color[1] = Neb2_fog_color[2] = 0;
}
// done, now free up the palette data
@@ -555,7 +553,7 @@ DCF(neb_skip, "Toggles culling of objects obscured by nebula")
}
int neb2_skip_render(object *objp, float z_depth)
{
float fog_near, fog_far;
float fog_near, fog_far, fog_density;
// if we're never skipping
if (!neb_skip_opt) {
@@ -563,7 +561,8 @@ int neb2_skip_render(object *objp, float z_depth)
}
// get near and far fog values based upon object type and rendering mode
neb2_get_adjusted_fog_values(&fog_near, &fog_far, objp);
neb2_get_adjusted_fog_values(&fog_near, &fog_far, &fog_density);
float fog = pow(fog_density, z_depth - fog_near + objp->radius);
// by object type
switch( objp->type ) {
@@ -579,34 +578,15 @@ int neb2_skip_render(object *objp, float z_depth)
// any weapon over 500 meters away
// Use the "far" distance multiplier here
case OBJ_WEAPON:
if (z_depth >= 500.0f * Neb2_fog_far_mult) {
if (fog < 0.05f) {
return 1;
}
break;
// any small ship over the fog limit, or any cruiser 50% further than the fog limit
// any ship less than 3% visible at their closest point
case OBJ_SHIP:
ship_info *sip;
if ( (objp->instance >= 0) && (Ships[objp->instance].ship_info_index >= 0) ) {
sip = &Ship_info[Ships[objp->instance].ship_info_index];
} else {
return 0;
}
// small ships over the fog limit by a small factor
if ( (sip->is_small_ship()) && (z_depth >= (fog_far * 1.5f)) ) {
if (fog < 0.03f)
return 1;
}
// big ships
if ( (sip->is_big_ship()) && (z_depth >= (fog_far * 2.0f)) ) {
return 1;
}
// huge ships
if ( (sip->is_huge_ship()) && (z_depth >= (fog_far * 3.0f)) ) {
return 1;
}
break;
// any fireball over the fog limit for small ships
@@ -619,11 +599,10 @@ int neb2_skip_render(object *objp, float z_depth)
return 0;
break;
// any asteroids 50% farther than the fog limit for small ships
// any asteroid less than 3% visible at their closest point
case OBJ_ASTEROID:
if (z_depth >= (fog_far * 1.5f)) {
if (fog < 0.03f)
return 1;
}
break;
// hmmm. unknown object type - should probably let it through
@@ -709,8 +688,8 @@ float neb2_get_alpha_2shell(float inner_radius, float outer_radius, float magic_
float neb2_get_alpha_offscreen(float sx, float sy, float incoming_alpha)
{
float alpha = 0.0f;
float per_pixel_x = incoming_alpha / (float)Nd->break_x;
float per_pixel_y = incoming_alpha / (float)Nd->break_y;
float per_pixel_x = incoming_alpha / (float)gr_screen.max_w;
float per_pixel_y = incoming_alpha / (float)gr_screen.max_h;
int off_x = ((sx < 0.0f) || (sx > (float)gr_screen.max_w));
int off_y = ((sy < 0.0f) || (sy > (float)gr_screen.max_h));
float off_x_amount = 0.0f;
@@ -1185,7 +1164,7 @@ void neb2_get_fog_values(float *fnear, float *ffar, object *objp)
}
// This version of the function allows for global adjustment to fog values
void neb2_get_adjusted_fog_values(float *fnear, float *ffar, object *objp)
void neb2_get_adjusted_fog_values(float *fnear, float *ffar, float *fdensity, object *objp)
{
neb2_get_fog_values(fnear, ffar, objp);
@@ -1196,33 +1175,36 @@ void neb2_get_adjusted_fog_values(float *fnear, float *ffar, object *objp)
// Avoide divide-by-zero
if ((*fnear - *ffar) == 0)
*ffar = *fnear + 1.0f;
if (fdensity != nullptr)
*fdensity = powf(NEB_FOG_FAR_PCT, 1 / (*ffar - *fnear));
}
float nNf_near, nNf_far;
float nNf_near, nNf_density;
// given a position in space, return a value from 0.0 to 1.0 representing the fog level
float neb2_get_fog_intensity(object *obj)
float neb2_get_fog_visibility(object *obj)
{
float pct;
float fog_far;
// get near and far fog values based upon object type and rendering mode
neb2_get_adjusted_fog_values(&nNf_near, &nNf_far, obj);
neb2_get_adjusted_fog_values(&nNf_near, &fog_far, &nNf_density, obj);
// get the fog pct
pct = vm_vec_dist_quick(&Eye_position, &obj->pos) / (nNf_far - nNf_near);
CLAMP(pct, 0.0f, 1.0f);
float pct = pow(nNf_density, vm_vec_dist(&Eye_position, &obj->pos) - nNf_near);
CLAMP(pct, 0.0f, 1.0f);
return pct;
}
//this only gets called after the one above has been called as it assumes you have set the near and far planes properly
//doun't use this outside of ship rendering
float neb2_get_fog_intensity(vec3d *pos)
//don't use this outside of ship rendering
float neb2_get_fog_visibility(vec3d *pos, float distance_mult)
{
float pct;
// get the fog pct
pct = vm_vec_dist_quick(&Eye_position, pos) / ((nNf_far*2) - nNf_near);
pct = powf(nNf_density, (vm_vec_dist(&Eye_position, pos) - nNf_near) / distance_mult);
CLAMP(pct, 0.0f, 1.0f);
@@ -1302,9 +1284,6 @@ void neb2_pre_render(camid cid)
}
}
// wacky scheme for smoothing colors
int wacky_scheme = 3;
// fill in the position of the eye for this frame
void neb2_get_eye_pos(vec3d *eye_vector)
{
@@ -1415,25 +1394,6 @@ DCF(neb2_break_alpha, "alpha value (0.0 to 1.0) at which faded polygons are not
dc_stuff_float(&Nd->break_alpha);
}
DCF(neb2_break_off, "how many pixels offscreen (left, right, top, bottom) when a cloud poof becomes fully transparent.")
{
int value;
dc_stuff_int(&value);
Nd->break_y = (float)value;
Nd->break_x = Nd->break_y * gr_screen.aspect;
}
DCF(neb2_smooth, "magic fog smoothing modes (0 - 3)")
{
int index;
dc_stuff_int(&index);
if ( (index >= 0) && (index <= 3) ) {
wacky_scheme = index;
} else {
dc_printf("Invalid smooth mode %i", index);
}
}
DCF(neb2_select, "Enables/disables a poof bitmap")
{
int bmap;
@@ -1507,7 +1467,7 @@ DCF(neb2_fog_color, "Sets the RGB fog color (HTL)")
dc_stuff_ubyte(&g);
dc_stuff_ubyte(&b);
Neb2_fog_color_r = r;
Neb2_fog_color_g = g;
Neb2_fog_color_b = b;
Neb2_fog_color[0] = r;
Neb2_fog_color[1] = g;
Neb2_fog_color[2] = b;
}
+21 -5
View File
@@ -40,6 +40,17 @@ extern float Neb2_awacs;
extern float Neb2_fog_near_mult;
extern float Neb2_fog_far_mult;
#define NEB_FOG_VISIBILITY_MULT_TRAIL 1.0f
#define NEB_FOG_VISIBILITY_MULT_THRUSTER 1.5f
#define NEB_FOG_VISIBILITY_MULT_WEAPON 1.3f
#define NEB_FOG_VISIBILITY_MULT_SHIELD 1.2f
#define NEB_FOG_VISIBILITY_MULT_GLOWPOINT 1.2f
#define NEB_FOG_VISIBILITY_MULT_BEAM(size) 4.0f + (size / 10)
#define NEB_FOG_VISIBILITY_MULT_B_MUZZLE(size) NEB_FOG_VISIBILITY_MULT_BEAM(size)
#define NEB_FOG_VISIBILITY_MULT_PARTICLE(size) 1.0f + (size / 12)
#define NEB_FOG_VISIBILITY_MULT_SHOCKWAVE 2.5f
#define NEB_FOG_VISIBILITY_MULT_FIREBALL(size) 1.2f + (size / 12)
#define MAX_NEB2_POOFS 32
// poof names and flags (for fred)
@@ -57,6 +68,9 @@ extern char Neb2_texture_name[MAX_FILENAME_LEN];
// how many "slices" are in the current player nebuls
extern int Neb2_slices;
// the color of the fog/background
extern ubyte Neb2_fog_color[3];
// nebula poofs
typedef struct cube_poof {
vec3d pt; // point in space
@@ -73,7 +87,6 @@ typedef struct neb2_detail {
float max_alpha_glide; // max alpha for this detail level in Glide
float max_alpha_d3d; // max alpha for this detail level in D3d
float break_alpha; // break alpha (below which, poofs don't draw). this affects the speed and visual quality a lot
float break_x, break_y; // x and y alpha fade/break values. adjust alpha on the polys as they move offscreen
float cube_dim; // total dimension of player poof cube
float cube_inner; // inner radius of the player poof cube
float cube_outer; // outer radius of the player pood cube
@@ -117,11 +130,14 @@ void neb2_eye_changed();
void neb2_get_fog_values(float *fnear, float *ffar, object *obj = NULL);
// get adjusted near and far fog values (allows mission-specific fog adjustments)
void neb2_get_adjusted_fog_values(float *fnear, float *ffar, object *obj = NULL);
void neb2_get_adjusted_fog_values(float *fnear, float *ffar, float *fdensity = nullptr, object *obj = nullptr);
// given a position in space, return a value from 0.0 to 1.0 representing the fog level
float neb2_get_fog_intensity(object *obj);
float neb2_get_fog_intensity(vec3d *pos);
// given an object, returns 0 - 1 the fog visibility of its center, 0 = completely obscured
float neb2_get_fog_visibility(object *obj);
// given a position, returns 0 - 1 the fog visibility of that position, 0 = completely obscured
// distance_mult will multiply the result, use for things that can be obscured but can 'shine through' the nebula more than normal
float neb2_get_fog_visibility (vec3d* pos, float distance_mult);
// should we not render this object because its obscured by the nebula?
int neb2_skip_render(object *objp, float z_depth);
+32 -7
View File
@@ -10,6 +10,7 @@
#include "globalincs/pstypes.h"
#include "network/chat_api.h"
#include "network/psnet2.h"
#include "network/multi_log.h"
#ifdef SCP_UNIX
#include <sys/time.h>
@@ -34,7 +35,7 @@ typedef int socklen_t;
#define MAXCHATBUFFER 500
SOCKET Chatsock;
SOCKET Chatsock = INVALID_SOCKET;
static SOCKADDR_STORAGE Chataddr;
int Socket_connecting = 0;
char Nick_name[33];
@@ -148,7 +149,6 @@ int ConnectToChatServer(char *serveraddr, char *nickname, char *trackerid)
if ( !psnet_get_addr(nullptr, static_cast<uint16_t>(0), &Chataddr) )
{
printf("bail!\n");
return -1;
}
@@ -216,6 +216,14 @@ int ConnectToChatServer(char *serveraddr, char *nickname, char *trackerid)
return 0;
}
// check for server error messages
const char *msg = ChatGetString();
if (msg && !strcmp(msg, "ERROR"))
{
return -1;
}
Socket_connected = 1;
memset(signon_str, 0, sizeof(signon_str));
sprintf_safe(signon_str, NOX("/USER %s %s %s :%s"), NOX("user"), NOX("user"), NOX("user"), Chat_tracker_id);
@@ -245,10 +253,18 @@ int ConnectToChatServer(char *serveraddr, char *nickname, char *trackerid)
*/
void DisconnectFromChatServer()
{
if(!Socket_connected) return;
SendChatString(NOX("/QUIT"),1);
shutdown(Chatsock,2);
closesocket(Chatsock);
if (Socket_connected)
{
SendChatString(NOX("/QUIT"), 1);
}
if (Chatsock != INVALID_SOCKET)
{
shutdown(Chatsock, 2);
closesocket(Chatsock);
}
Chatsock = INVALID_SOCKET;
Socket_connecting = 0;
Socket_connected = 0;
Input_chat_buffer[0] = '\0';
@@ -466,7 +482,7 @@ char *ChatGetString(void)
FD_ZERO(&read_fds);
FD_SET(Chatsock,&read_fds);
//Writable -- that means it's connected
while ( select(static_cast<int>(Chatsock+1), &read_fds, nullptr, nullptr, &timeout) )
while ( select(static_cast<int>(Chatsock+1), &read_fds, nullptr, nullptr, &timeout) > 0 )
{
bytesread = recv(Chatsock,ch,1,0);
if(bytesread)
@@ -777,6 +793,15 @@ char * ParseIRCMessage(char *Line, int iMode)
return NULL;
}
if(stricmp(szCmd,NOX("ERROR"))==0)
{
// Server reported errors
ml_printf("Chat ERROR: %s", szRemLine);
AddChatCommandToQueue(CC_DISCONNECTED, nullptr, 0);
strcpy_s(szResponse, "ERROR");
return szResponse;
}
if(stricmp(szCmd,NOX("NOTICE"))==0)
{
+4
View File
@@ -569,6 +569,10 @@ void process_packet_normal(ubyte* data, header *header_info)
process_ship_kill_packet( data, header_info );
break;
case MISSILE_KILL:
process_weapon_kill_packet(data, header_info);
break;
case WING_CREATE:
process_wing_create_packet( data, header_info );
break;
+3 -1
View File
@@ -66,9 +66,10 @@ class player;
// version 51 - 9/20/2020 Object Update Packet Upgrade: Waypoints, subsystem rotation, bandwidth improvements, bugfixes
// version 52 - 10/9/2020 Dumbfire Rollback, increases accuracy of high ping, or delayed packet primary fire for clients.
// version 53 - 12/2/2020 big set of packet fixes/upgrades
// version 54 - 3/20/2021 - Fixes for FSO 21_2 especially better net_sig calc, better missile intercept
// STANDALONE_ONLY
#define MULTI_FS_SERVER_VERSION 53
#define MULTI_FS_SERVER_VERSION 54
#define MULTI_FS_SERVER_COMPATIBLE_VERSION MULTI_FS_SERVER_VERSION
@@ -252,6 +253,7 @@ class player;
#define REINFORCEMENT_AVAIL 0xDB // a reinforcement is available
#define LIGHTNING_PACKET 0xDC // lightning bolt packet for multiplayer nebula
#define BYTES_SENT 0xDD // how much data we've sent/received
#define MISSILE_KILL 0xDE // get rid of this weapon on the client.
#define GAME_ACTIVE 0xE1 // info on an active game server
#define GAME_QUERY 0xE2 // request for a list of active game servers
+2 -2
View File
@@ -639,7 +639,7 @@ void multi_ship_record_do_rollback()
}
objp = &Objects[cur_ship.objnum];
if (objp == nullptr) {
if (objp == nullptr || objp->type != OBJ_SHIP) {
continue;
}
@@ -3387,7 +3387,7 @@ void multi_oo_calc_interp_splines(int player_id, object* objp, matrix *new_orien
float delta = multi_oo_calc_pos_time_difference(player_id, net_sig_idx);
// if an error or invalid value, use the local timestamps instead of those received. Should be rare.
if (delta <= 0.0f) {
delta = (float)(timestamp() - Oo_info.received_frametimes[player_id].at(Oo_info.interp[net_sig_idx].pos_timestamp)) / TIMESTAMP_FREQUENCY;
delta = (float)(timestamp() - Oo_info.interp[net_sig_idx].pos_timestamp) / TIMESTAMP_FREQUENCY;
}
Oo_info.interp[net_sig_idx].pos_time_delta = delta;
+23 -14
View File
@@ -644,9 +644,14 @@ void multi_respawn_process_packet(ubyte *data, header *hinfo)
p_object *pobjp;
GET_USHORT( net_sig );
pobjp = mission_parse_get_arrival_ship( net_sig );
Assert( pobjp != NULL );
multi_respawn_ai( pobjp );
// only attempt to respawn if we are in the mission
if (!(Net_player->flags & NETINFO_FLAG_WARPING_OUT)) {
pobjp = mission_parse_get_arrival_ship(net_sig);
Assert(pobjp != NULL);
multi_respawn_ai(pobjp);
}
break;
case RESPAWN_BROADCAST:
@@ -659,19 +664,23 @@ void multi_respawn_process_packet(ubyte *data, header *hinfo)
GET_DATA(cur_link_status);
GET_USHORT(ship_ets);
GET_STRING(parse_name);
player_index = find_player_id(player_id);
if(player_index == -1){
nprintf(("Network","Couldn't find player to respawn!\n"));
break;
}
// create the ship and assign its position, net_signature, and class
// respawn the player
multi_respawn_player(&Net_players[player_index], cur_primary_bank, cur_secondary_bank, cur_link_status, ship_ets, net_sig, parse_name, &v);
if (!(Net_player->flags & NETINFO_FLAG_WARPING_OUT)) {
player_index = find_player_id(player_id);
// if this is for me, I should jump back into gameplay
if(&Net_players[player_index] == Net_player){
gameseq_post_event(GS_EVENT_ENTER_GAME);
if(player_index == -1){
nprintf(("Network","Couldn't find player to respawn!\n"));
break;
}
// create the ship and assign its position, net_signature, and class
// respawn the player
multi_respawn_player(&Net_players[player_index], cur_primary_bank, cur_secondary_bank, cur_link_status, ship_ets, net_sig, parse_name, &v);
// if this is for me, I should jump back into gameplay
if(&Net_players[player_index] == Net_player){
gameseq_post_event(GS_EVENT_ENTER_GAME);
}
}
break;
+123 -11
View File
@@ -2700,6 +2700,71 @@ void process_ship_kill_packet( ubyte *data, header *hinfo )
}
}
constexpr int WK_FLAGS_WEAPON_WEAPON = (1<<0);
// simply removes a missile from existence on the client.
void send_missile_kill_packet(object* objp)
{
Assert(objp != nullptr);
Assert(objp->type == OBJ_WEAPON);
Assert(MULTIPLAYER_MASTER);
if (objp == nullptr || objp->type != OBJ_WEAPON || MULTIPLAYER_CLIENT || !(Weapon_info[Weapons[objp->instance].weapon_info_index].subtype & WP_MISSILE)) {
return;
}
ubyte data[MAX_PACKET_SIZE], flags = 0;
int packet_size;
BUILD_HEADER(MISSILE_KILL);
ADD_USHORT(objp->net_signature);
if (objp->instance > -1) {
if (Weapons[objp->instance].weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon])
flags |= WK_FLAGS_WEAPON_WEAPON;
}
ADD_DATA(flags);
multi_io_send_to_all_reliable(data, packet_size);
}
void process_weapon_kill_packet(ubyte *data, header *hinfo )
{
// only masters should receive this packet.
Assert(MULTIPLAYER_CLIENT);
int offset = HEADER_LENGTH;
ushort missile_net_signature;
ubyte flags;
GET_USHORT(missile_net_signature);
GET_DATA(flags);
PACKET_SET_SIZE();
// get the object pointer for the missile
object* missile = multi_get_network_object(missile_net_signature);
// make sure it's valid before implementing.
if (missile == nullptr || missile->type != OBJ_WEAPON || missile->instance < 0 || !(Weapon_info[Weapons[missile->instance].weapon_info_index].subtype & WP_MISSILE)) {
return;
}
// set any optional packets.
if (flags & WK_FLAGS_WEAPON_WEAPON) {
Weapons[missile->instance].weapon_flags.set(Weapon::Weapon_Flags::Destroyed_by_weapon);
}
// kill the missile!
if (Weapon_info[Weapons[missile->instance].weapon_info_index].weapon_hitpoints > 0.0f) {
missile->hull_strength = -1.0f;
}
weapon_detonate(missile);
missile->flags.set(Object::Object_Flags::Should_be_dead);
Weapons[missile->instance].lifeleft = -1.0f;
}
// send a packet indicating a ship should be created
void send_ship_create_packet( object *objp, bool is_support )
{
@@ -7428,11 +7493,12 @@ void process_debrief_info( ubyte *data, header *hinfo )
debrief_set_multi_clients( stage_counts[Net_player->p_info.team], stages[Net_player->p_info.team] );
}
constexpr ubyte HWIF_BIG_UPDATE = (1 << 0);
// sends homing information to all clients. We only need signature and num_missiles (because of hornets).
// sends homing_object and homing_subsystem to all clients.
void send_homing_weapon_info( int weapon_num )
{
ubyte data[MAX_PACKET_SIZE];
ubyte data[MAX_PACKET_SIZE], flags = 0;
int s_index;
int packet_size;
object *homing_object;
@@ -7452,6 +7518,7 @@ void send_homing_weapon_info( int weapon_num )
// homing signature.
homing_signature = 0;
homing_object = wp->homing_object;
if ( homing_object != &obj_used_list ) {
homing_signature = homing_object->net_signature;
@@ -7461,11 +7528,26 @@ void send_homing_weapon_info( int weapon_num )
}
}
if (!wp->weapon_flags[Weapon::Weapon_Flags::Multi_Update_Sent] || IS_MAT_NULL(&Objects[wp->objnum].phys_info.ai_desired_orient)) {
flags |= HWIF_BIG_UPDATE;
wp->weapon_flags.set(Weapon::Weapon_Flags::Multi_Update_Sent);
}
BUILD_HEADER(HOMING_WEAPON_UPDATE);
ADD_DATA(flags);
ADD_USHORT( Objects[wp->objnum].net_signature );
ADD_USHORT( homing_signature );
ADD_SHORT( static_cast<short>(s_index) );
ADD_VECTOR( wp->homing_pos);
if (flags & HWIF_BIG_UPDATE) {
fix current_lifetime = Missiontime - wp->creation_time;
ADD_INT(current_lifetime);
ADD_VECTOR(Objects[wp->objnum].pos);
ADD_FLOAT(wp->launch_speed);
ADD_ORIENT(Objects[wp->objnum].orient);
}
multi_io_send_to_all(data, packet_size);
}
@@ -7473,56 +7555,86 @@ void send_homing_weapon_info( int weapon_num )
// packet contains information for multiple weapons (like hornets).
void process_homing_weapon_info( ubyte *data, header *hinfo )
{
ubyte flags;
int offset;
fix missile_lifetime = 0;
ushort weapon_signature, homing_signature;
short h_subsys;
float launch_speed = 0.0f;
vec3d missile_pos = vmd_zero_vector, homing_goal = vmd_zero_vector;
object *homing_object, *weapon_objp;
weapon *wp;
matrix orient_in = vmd_identity_matrix;
offset = HEADER_LENGTH;
// get the data for the packet
GET_DATA(flags);
GET_USHORT( weapon_signature );
GET_USHORT( homing_signature );
GET_SHORT( h_subsys );
GET_VECTOR( homing_goal );
if (flags & HWIF_BIG_UPDATE) {
GET_INT(missile_lifetime);
GET_VECTOR(missile_pos);
GET_FLOAT(launch_speed);
GET_ORIENT(orient_in);
}
PACKET_SET_SIZE();
// deal with changing this weapons homing information
weapon_objp = multi_get_network_object( weapon_signature );
if ( weapon_objp == NULL ) {
if ( weapon_objp == nullptr ) {
nprintf(("Network", "Couldn't find weapon object for homing update -- skipping update\n"));
return;
}
Assert( weapon_objp->type == OBJ_WEAPON );
wp = &Weapons[weapon_objp->instance];
// be sure that we can find these weapons and
homing_object = multi_get_network_object( homing_signature );
if ( homing_object == NULL ) {
if ( homing_object == nullptr ) {
wp->homing_object = &obj_used_list;
wp->homing_subsys = nullptr;
wp->target_num = -1;
wp->target_sig = -1;
nprintf(("Network", "Couldn't find homing object for homing update\n"));
return;
}
}
if ( homing_object->type == OBJ_WEAPON ) {
auto flags = Weapon_info[Weapons[homing_object->instance].weapon_info_index].wi_flags;
auto flags_check = Weapon_info[Weapons[homing_object->instance].weapon_info_index].wi_flags;
// Assert( (flags & WIF_BOMB) || (flags & WIF_CMEASURE) );
if ( !((flags[Weapon::Info_Flags::Bomb, Weapon::Info_Flags::Cmeasure])) ) {
if ( !((flags_check[Weapon::Info_Flags::Bomb, Weapon::Info_Flags::Cmeasure])) ) {
nprintf(("Network", "Homing object is invalid for homing update\n"));
return;
}
}
wp->homing_object = homing_object;
wp->homing_subsys = NULL;
wp->homing_subsys = nullptr;
wp->target_num = OBJ_INDEX(homing_object);
wp->target_sig = homing_object->signature;
wp->homing_pos = homing_goal;
if ( h_subsys != -1 ) {
Assert( homing_object->type == OBJ_SHIP );
wp->homing_subsys = ship_get_indexed_subsys( &Ships[homing_object->instance], h_subsys);
}
if (flags & HWIF_BIG_UPDATE) {
wp->creation_time = Missiontime + missile_lifetime;
weapon_objp->pos = missile_pos;
weapon_objp->orient = orient_in;
wp->launch_speed = launch_speed;
}
if ( homing_object->type == OBJ_SHIP ) {
nprintf(("Network", "Updating homing information for weapon -- homing on %s\n", Ships[homing_object->instance].ship_name));
}
+5
View File
@@ -295,6 +295,11 @@ void send_object_update_packet(int force_all = 0);
// send a packet indicating a ship has been killed
void send_ship_kill_packet( object *ship_obj, object *other_objp, float percent_killed, int self_destruct );
// send a packet indicating that a missile died.
void send_missile_kill_packet(object* objp);
void process_weapon_kill_packet(ubyte* data, header* hinfo);
// send a packet indicating a wing of ships should be created
void send_wing_create_packet( wing *wingp, int num_to_create, int pre_create_count );
+32 -22
View File
@@ -3522,25 +3522,25 @@ int multi_pack_unpack_vel( int write, ubyte *data, matrix *orient, physics_info
f = vm_vec_dot( &orient->vec.fvec, &pi->vel );
// Cyborg17 - using round here allows us keep part of the decimal accuracy that would have been dropped with just fl2i
a = fl2i(round(r * 2.0f));
b = fl2i(round(u * 2.0f));
c = fl2i(round(f * 4.0f));
CAP(a,-512,511);
CAP(b,-512,511);
CAP(c,-2048,2047);
bitbuffer_put( &buf, (uint)a, 10 );
bitbuffer_put( &buf, (uint)b, 10 );
bitbuffer_put( &buf, (uint)c, 12 );
a = fl2i(round(r * 16.0f));
b = fl2i(round(u * 16.0f));
c = fl2i(round(f * 32.0f));
CAP(a,-2048,2047);
CAP(b,-2048,2047);
CAP(c,-4096,4095);
bitbuffer_put( &buf, (uint)a, 13 );
bitbuffer_put( &buf, (uint)b, 13 );
bitbuffer_put( &buf, (uint)c, 14 );
return bitbuffer_write_flush(&buf);
} else {
// unpack velocity
a = bitbuffer_get_signed(&buf,10);
b = bitbuffer_get_signed(&buf,10);
c = bitbuffer_get_signed(&buf,12);
r = i2fl(a)/2.0f;
u = i2fl(b)/2.0f;
f = i2fl(c)/4.0f;
a = bitbuffer_get_signed(&buf,13);
b = bitbuffer_get_signed(&buf,13);
c = bitbuffer_get_signed(&buf,14);
r = i2fl(a)/16.0f;
u = i2fl(b)/16.0f;
f = i2fl(c)/32.0f;
// Convert into world coordinates
vm_vec_zero(&pi->vel);
@@ -3574,7 +3574,6 @@ int multi_pack_unpack_rotvel( int write, ubyte *data, physics_info *pi)
bitbuffer_put( &buf, (uint)b, 10 );
bitbuffer_put( &buf, (uint)c, 10 );
return bitbuffer_write_flush(&buf);
} else {
@@ -3600,6 +3599,11 @@ int multi_pack_unpack_desired_vel_and_desired_rotvel( int write, bool full_physi
int a = 0, b = 0, c = 0;
int d = 0, e = 0, f = 0;
// we could have reduced it to 8 when full physics is false, and saved the byte,
// but this ends up allowing us more accuracy during capship warpin/out
const int z_bitcount = (full_physics) ? 9 : 16;
const int z_capfactor = (full_physics) ? 255 : 32640;
if ( write ) {
if (full_physics) {
// output desired rotational velocity
@@ -3632,17 +3636,20 @@ int multi_pack_unpack_desired_vel_and_desired_rotvel( int write, bool full_physi
if (pi->max_vel.xyz.y > 0.0f) {
e = fl2i(round( (local_desired_vel->xyz.y / pi->max_vel.xyz.y) * 7.0f));
}
// for z velocity, take into account afterburner.
if (pi->max_vel.xyz.z > 0.0f) {
f = fl2i(round( (local_desired_vel->xyz.z / pi->afterburner_max_vel.xyz.z) * 255.0f));
float z_divisor = MAX(pi->afterburner_max_vel.xyz.z, pi->max_vel.xyz.z);
if (z_divisor > 0.0f) {
f = fl2i(round( (local_desired_vel->xyz.z / z_divisor) * 255.0f));
}
CAP(d,-7,7);
CAP(e,-7,7);
CAP(f,-255,255);
CAP(f,-z_capfactor,z_capfactor);
bitbuffer_put( &buf, (uint)d,4);
bitbuffer_put( &buf, (uint)e,4);
bitbuffer_put( &buf, (uint)f,9);
bitbuffer_put( &buf, (uint)f,z_bitcount); // either 9 or 16 bits.
return bitbuffer_write_flush(&buf);
@@ -3662,10 +3669,13 @@ int multi_pack_unpack_desired_vel_and_desired_rotvel( int write, bool full_physi
// unpack desired velocity
d = bitbuffer_get_signed(&buf,4);
e = bitbuffer_get_signed(&buf,4);
f = bitbuffer_get_signed(&buf,9);
f = bitbuffer_get_signed(&buf,z_bitcount); // either 9 or 16 bits.
local_desired_vel->xyz.x = pi->max_vel.xyz.x * i2fl(d)/7.0f;
local_desired_vel->xyz.y = pi->max_vel.xyz.y * i2fl(e)/7.0f;
local_desired_vel->xyz.z = pi->afterburner_max_vel.xyz.z * i2fl(f)/255.0f;
float z_multiplier = MAX(pi->afterburner_max_vel.xyz.z, pi->max_vel.xyz.z);
local_desired_vel->xyz.z = z_multiplier * i2fl(f)/255.0f;
return bitbuffer_read_flush(&buf);
+2 -1
View File
@@ -94,7 +94,8 @@ int collide_weapon_weapon( obj_pair * pair )
bool b_override = Script_system.IsConditionOverride(CHA_COLLIDEWEAPON, B);
Script_system.RemHookVars({ "Self", "Object", "Weapon", "WeaponB", "Hitpos" });
if(!a_override && !b_override)
// damage calculation should not be done on clients, the server will tell the client version of the bomb when to die
if(!a_override && !b_override && !MULTIPLAYER_CLIENT)
{
float aDamage = wipA->damage;
if (wipB->armor_type_idx >= 0)
+3 -3
View File
@@ -178,7 +178,7 @@ void obj_render_all(const std::function<void(object*)>& render_function, bool *d
{
object *objp;
int i;
float fog_near, fog_far;
float fog_near, fog_far, fog_density;
objp = Objects;
@@ -244,7 +244,7 @@ void obj_render_all(const std::function<void(object*)>& render_function, bool *d
// if we're fullneb, fire up the fog - this also generates a fog table
if (full_neb) {
// get the fog values
neb2_get_adjusted_fog_values(&fog_near, &fog_far, obj);
neb2_get_adjusted_fog_values(&fog_near, &fog_far, &fog_density, obj);
// maybe skip rendering an object because its obscured by the nebula
if(neb2_skip_render(obj, os->z)){
@@ -281,7 +281,7 @@ void obj_render_all(const std::function<void(object*)>& render_function, bool *d
// if we're fullneb, fire up the fog - this also generates a fog table
if(full_neb){
// get the fog values
neb2_get_adjusted_fog_values(&fog_near, &fog_far, obj);
neb2_get_adjusted_fog_values(&fog_near, &fog_far, &fog_density, obj);
// maybe skip rendering an object because its obscured by the nebula
if(neb2_skip_render(obj, os->z)){
+80 -86
View File
@@ -2229,36 +2229,26 @@ void read_raw_file_text(const char *filename, int mode, char *raw_text)
// SDL2 has iconv functionality so we use that to convert from Latin1 to UTF-8
// We need the raw_text as the output buffer so we first need to copy the current
// We need the raw_text as fallback so we first need to copy the current
SCP_string input_str = raw_text;
do {
auto in_str = input_str.c_str();
auto in_size = input_str.size();
auto out_str = Parse_text_raw;
auto out_size = Parse_text_size;
SCP_string buffer;
bool success = unicode::convert_encoding(buffer, raw_text, unicode::Encoding::Encoding_iso8859_1, unicode::Encoding::Encoding_utf8);
auto iconv = SDL_iconv_open("UTF-8", "ISO-8859-1");
auto err = SDL_iconv(iconv, &in_str, &in_size, &out_str, &out_size);
SDL_iconv_close(iconv);
if (Parse_text_size < buffer.length()) {
allocate_parse_text(buffer.length());
}
// SDL returns the number of processed character on success;
// error codes are (size_t)-1 through -4
if (err < (size_t)-100) {
break;
} else if (err == SDL_ICONV_E2BIG) {
// buffer is not big enough, try again with a bigger buffer. Use a rather conservative size
// increment since the additional size required is probably pretty small
allocate_parse_text(Parse_text_size + 300);
} else {
Warning(LOCATION, "File reencoding failed (error code " SIZE_T_ARG ")!\n"
"You will probably encounter encoding issues.", err);
if (success) {
strncpy(Parse_text_raw, buffer.c_str(), buffer.length());
}
else {
Warning(LOCATION, "File reencoding failed!\n"
"You will probably encounter encoding issues.");
// Copy the original data back to the mission text pointer so that we don't loose any data here
strcpy(Parse_text_raw, input_str.c_str());
break;
}
} while(true);
// Copy the original data back to the mission text pointer so that we don't loose any data here
strcpy(Parse_text_raw, input_str.c_str());
}
} else {
Warning(LOCATION, "Found invalid UTF-8 encoding in file %s at position " PTRDIFF_T_ARG "!\n"
"This may cause parsing errors and should be fixed!", filename, invalid - raw_text);
@@ -2288,41 +2278,7 @@ void coerce_to_utf8(SCP_string &buffer, const char *str)
// we can convert it
if (isLatin1)
{
size_t newlen = len;
std::unique_ptr<char[]> newstr(new char[newlen]);
do {
auto in_str = str;
auto in_size = len;
auto out_str = newstr.get();
auto out_size = newlen;
auto iconv = SDL_iconv_open("UTF-8", "ISO-8859-1");
auto err = SDL_iconv(iconv, &in_str, &in_size, &out_str, &out_size);
SDL_iconv_close(iconv);
// SDL returns the number of processed character on success;
// error codes are (size_t)-1 through -4
if (err < (size_t)-100)
{
// successful re-encoding
buffer.assign(newstr.get(), newlen - out_size);
mprintf(("Re-encoding non-UTF-8 string '%s' to '%s'!\n", str, buffer.c_str()));
return;
}
else if (err == SDL_ICONV_E2BIG)
{
// buffer is not big enough, try again with a bigger buffer. Use a rather conservative size
// increment since the additional size required is probably pretty small
newlen += 10;
newstr.reset(new char[newlen]);
}
else
{
// re-encoding failed, so use truncation
break;
}
} while (true);
unicode::convert_encoding(buffer, str, unicode::Encoding::Encoding_iso8859_1, unicode::Encoding::Encoding_utf8);
}
// unknown encoding, so just truncate
@@ -2331,10 +2287,19 @@ void coerce_to_utf8(SCP_string &buffer, const char *str)
}
// Goober5000
void process_raw_file_text(char *processed_text, char *raw_text)
void process_raw_file_text(char* processed_text, char* raw_text)
{
char *mp;
char *mp_raw;
SCP_string parse_exception_1402;
unicode::convert_encoding(parse_exception_1402, "1402, \"Sie haben IPX-Protokoll als Protokoll ausgew\xE4hlt, aber dieses Protokoll ist auf Ihrer Maschine nicht installiert.\".\"\n", unicode::Encoding::Encoding_iso8859_1);
SCP_string parse_exception_1117;
unicode::convert_encoding(parse_exception_1117, "1117, \"\\r\\n\"Aucun web browser trouva. Del\xE0 isn't on emm\xE9nagea ou if \\r\\non est emm\xE9nagea, ca isn't set pour soient la default browser.\\r\\n\\r\\n\"\n", unicode::Encoding::Encoding_iso8859_1);
SCP_string parse_exception_1337;
unicode::convert_encoding(parse_exception_1337, "1337, \"(fr)Loading\"\n", unicode::Encoding::Encoding_iso8859_1);
SCP_string parse_exception_3966;
unicode::convert_encoding(parse_exception_3966, "3966, \"Es sieht so aus, als habe Staffel Kappa Zugriff auf die GTVA-Zugangscodes f\xFCr das System gehabt. Das ist ein ernstes Sicherheitsleck. Ihre IFF-Kennung erschien als \"verb\xFCndet\", so da\xDF sie sich dem Konvoi ungehindert n\xE4hern konnten. Zum Gl\xFC\x63k flogen Sie und Alpha 2 Geleitschutz und lie\xDF\x65n den Schwindel auffliegen, bevor Kappa ihren Befehl ausf\xFChren konnte.\"\n", unicode::Encoding::Encoding_iso8859_1);
char* mp;
char* mp_raw;
char outbuf[PARSE_BUF_SIZE];
bool in_quote = false;
bool in_multiline_comment_a = false;
@@ -2347,32 +2312,38 @@ void process_raw_file_text(char *processed_text, char *raw_text)
if (raw_text == NULL)
raw_text = Parse_text_raw;
Assert( processed_text != NULL );
Assert( raw_text != NULL );
Assert(processed_text != NULL);
Assert(raw_text != NULL);
mp = processed_text;
mp_raw = raw_text;
// strip comments from raw text, reading into file_text
int num_chars_read = 0;
while ( (num_chars_read = parse_get_line(outbuf, PARSE_BUF_SIZE, raw_text, raw_text_len, mp_raw)) != 0 ) {
while ((num_chars_read = parse_get_line(outbuf, PARSE_BUF_SIZE, raw_text, raw_text_len, mp_raw)) != 0) {
mp_raw += num_chars_read;
// stupid hacks to make retail data work with fixed parser, per Mantis #3072
if (!strcmp(outbuf, "1402, \"Sie haben IPX-Protokoll als Protokoll ausgew\xE4hlt, aber dieses Protokoll ist auf Ihrer Maschine nicht installiert.\".\"\n")) {
outbuf[121] = ' ';
outbuf[122] = ' ';
} else if (!strcmp(outbuf, "1117, \"\\r\\n\"Aucun web browser trouva. Del\xE0 isn't on emm\xE9nagea ou if \\r\\non est emm\xE9nagea, ca isn't set pour soient la default browser.\\r\\n\\r\\n\"\n")) {
char *ch = &outbuf[11];
if (!strcmp(outbuf, parse_exception_1402.c_str())) {
int offset = Unicode_text_mode ? 1 : 0;
outbuf[121 + offset] = ' ';
outbuf[122 + offset] = ' ';
}
else if (!strcmp(outbuf, parse_exception_1117.c_str())) {
char* ch = &outbuf[11];
do {
*ch = *(ch+1);
*ch = *(ch + 1);
++ch;
} while (*ch);
} else if (!strcmp(outbuf, "1337, \"(fr)Loading\"\n")) {
}
else if (!strcmp(outbuf, parse_exception_1337.c_str())) {
outbuf[3] = '6';
} else if (!strcmp(outbuf, "3966, \"Es sieht so aus, als habe Staffel Kappa Zugriff auf die GTVA-Zugangscodes f\xFCr das System gehabt. Das ist ein ernstes Sicherheitsleck. Ihre IFF-Kennung erschien als \"verb\xFCndet\", so da\xDF sie sich dem Konvoi ungehindert n\xE4hern konnten. Zum Gl\xFC\x63k flogen Sie und Alpha 2 Geleitschutz und lie\xDF\x65n den Schwindel auffliegen, bevor Kappa ihren Befehl ausf\xFChren konnte.\"\n")) {
outbuf[171] = '\'';
outbuf[181] = '\'';
}
else if (!strcmp(outbuf, parse_exception_3966.c_str())) {
int offset = Unicode_text_mode ? 1 : 0;
outbuf[171 + offset] = '\'';
outbuf[181 + offset * 2] = '\'';
}
strip_comments(outbuf, in_quote, in_multiline_comment_a, in_multiline_comment_b);
@@ -2819,6 +2790,9 @@ size_t stuff_token_list(T *listp, size_t list_max, F stuff_one_token, const char
return i;
}
// If this data is going to be parsed multiple times (like for mission load), then the dest variable
// needs to be set to zero in between parses, otherwise we keep bad data.
// For tbm files, it must not be reset.
void parse_string_flag_list(int *dest, flag_def_list defs[], size_t defs_size)
{
Assert(dest!=NULL); //wtf?
@@ -3018,16 +2992,18 @@ void stuff_loadout_list(SCP_vector<loadout_row> &list, int lookup_type)
Warning(LOCATION, "Weapon '%s' has more than 300 possible spawned weapons over its lifetime! This can cause issues for Multiplayer.", Weapon_info[buf->index].name);
}
// similarly, complain if this is a valid ship or weapon class that the player can't use
if ((lookup_type == MISSION_LOADOUT_SHIP_LIST) && (!(Ship_info[buf->index].flags[Ship::Info_Flags::Player_ship])) ) {
error_display(0, "Ship type \"%s\" found in loadout of mission file. This class is not marked as a player ship...skipping", str.c_str());
skip_this_entry = true;
}
else if ((lookup_type == MISSION_LOADOUT_WEAPON_LIST) && (!(Weapon_info[buf->index].wi_flags[Weapon::Info_Flags::Player_allowed])) ) {
nprintf(("Warning", "Warning: Weapon type %s found in loadout of mission file. This class is not marked as a player allowed weapon...skipping\n", str.c_str()));
if ( !Is_standalone )
error_display(0, "Weapon type \"%s\" found in loadout of mission file. This class is not marked as a player allowed weapon...skipping", str.c_str());
skip_this_entry = true;
if (!skip_this_entry) {
// similarly, complain if this is a valid ship or weapon class that the player can't use
if ((lookup_type == MISSION_LOADOUT_SHIP_LIST) && (!(Ship_info[buf->index].flags[Ship::Info_Flags::Player_ship])) ) {
error_display(0, "Ship type \"%s\" found in loadout of mission file. This class is not marked as a player ship...skipping", str.c_str());
skip_this_entry = true;
}
else if ((lookup_type == MISSION_LOADOUT_WEAPON_LIST) && (!(Weapon_info[buf->index].wi_flags[Weapon::Info_Flags::Player_allowed])) ) {
nprintf(("Warning", "Warning: Weapon type %s found in loadout of mission file. This class is not marked as a player allowed weapon...skipping\n", str.c_str()));
if ( !Is_standalone )
error_display(0, "Weapon type \"%s\" found in loadout of mission file. This class is not marked as a player allowed weapon...skipping", str.c_str());
skip_this_entry = true;
}
}
// Loadout counts are only needed for missions
@@ -3889,6 +3865,24 @@ int get_index_of_first_hash_symbol(SCP_string &src, bool ignore_doubled_hash)
}
}
// Goober5000
// Used for escape sequences: ## to #, !! to !, etc.
void consolidate_double_characters(char *src, char ch)
{
auto dest = src;
while (*src)
{
if (*src == ch && *(src + 1) == ch)
dest--;
++src;
++dest;
if (src != dest)
*dest = *src;
}
}
// Goober5000
ptrdiff_t replace_one(char *str, const char *oldstr, const char *newstr, size_t max_len, ptrdiff_t range)
{
+2
View File
@@ -74,6 +74,8 @@ extern char *get_pointer_to_first_hash_symbol(char *src, bool ignore_doubled_has
extern const char *get_pointer_to_first_hash_symbol(const char *src, bool ignore_doubled_hash = false);
extern int get_index_of_first_hash_symbol(SCP_string &src, bool ignore_doubled_hash = false);
extern void consolidate_double_characters(char *str, char ch);
// white space
extern int is_white_space(char ch);
extern int is_white_space(unicode::codepoint_t cp);
+114 -15
View File
@@ -679,6 +679,7 @@ SCP_vector<sexp_oper> Operators = {
{ "nebula-change-storm", OP_NEBULA_CHANGE_STORM, 1, 1, SEXP_ACTION_OPERATOR, }, // phreak
{ "nebula-toggle-poof", OP_NEBULA_TOGGLE_POOF, 2, 2, SEXP_ACTION_OPERATOR, }, // phreak
{ "nebula-change-pattern", OP_NEBULA_CHANGE_PATTERN, 1, 1, SEXP_ACTION_OPERATOR, }, // Axem
{ "nebula-change-fog-color", OP_NEBULA_CHANGE_FOG_COLOR, 3, 3, SEXP_ACTION_OPERATOR, }, // Asteroth
{ "set-skybox-model", OP_SET_SKYBOX_MODEL, 1, 8, SEXP_ACTION_OPERATOR, }, // taylor
{ "set-skybox-orientation", OP_SET_SKYBOX_ORIENT, 3, 3, SEXP_ACTION_OPERATOR, }, // Goober5000
{ "set-ambient-light", OP_SET_AMBIENT_LIGHT, 3, 3, SEXP_ACTION_OPERATOR, }, // Karajorma
@@ -3390,7 +3391,9 @@ void get_sexp_text_for_variable(char *text, const char *token)
if ( !Fred_running ) {
// freespace - get index into Sexp_variables array
sexp_var_index = get_index_sexp_variable_name(text);
Assert(sexp_var_index != -1);
if (sexp_var_index == -1) {
Error(LOCATION, "Invalid variable name [%s]!", text);
}
sprintf(text, "%d", sexp_var_index);
}
}
@@ -6838,7 +6841,21 @@ int sexp_is_ship_visible(int node)
{
// if the second argument is not supplied, default to the player, per retail
if (Game_mode & GM_MULTIPLAYER)
Warning(LOCATION, "In multiplayer, is-ship-visible must have two arguments!");
{
mprintf(("In multiplayer, is-ship-visible must have two arguments! Defaulting to the first player.\n"));
// to make allowances for buggy missions (such as retail), just pick the first player
// if we actually have no valid players, viewer_shipp will be NULL, but that's ok
for (int i = 0; i < MAX_PLAYERS; ++i)
{
int shipnum = multi_get_player_ship(i);
if (shipnum >= 0)
{
viewer_shipp = &Ships[shipnum];
break;
}
}
}
else
viewer_shipp = Player_ship;
}
@@ -10000,7 +10017,7 @@ int eval_in_sequence(int arg_handler_node, int condition_node)
}
// Goober5000
int eval_for_counter(int arg_handler_node, int condition_node)
int eval_for_counter(int arg_handler_node, int condition_node, bool just_count = false)
{
bool is_nan, is_nan_forever;
int n, num_valid_arguments, num_true, num_false, num_known_true, num_known_false;
@@ -10050,6 +10067,9 @@ int eval_for_counter(int arg_handler_node, int condition_node)
// situation, resulting in a crash at best. -MageKing17
}
if (just_count)
return static_cast<int>(argument_vector.size());
// test the whole argument vector
num_valid_arguments = test_argument_vector_for_condition(argument_vector, true, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
@@ -10063,7 +10083,7 @@ int eval_for_counter(int arg_handler_node, int condition_node)
}
// Goober5000
int eval_for_ship_collection(int arg_handler_node, int condition_node, int op_num)
int eval_for_ship_collection(int arg_handler_node, int condition_node, int op_const, bool just_count = false)
{
int n, num_valid_arguments, num_true, num_false, num_known_true, num_known_false;
SCP_vector<std::pair<char*, int>> argument_vector;
@@ -10077,7 +10097,7 @@ int eval_for_ship_collection(int arg_handler_node, int condition_node, int op_nu
auto constraint = CTEXT(n);
int constraint_index = -1;
switch (op_num)
switch (op_const)
{
case OP_FOR_SHIP_CLASS:
constraint_index = ship_info_lookup(constraint);
@@ -10104,7 +10124,7 @@ int eval_for_ship_collection(int arg_handler_node, int condition_node, int op_nu
auto shipp = &Ships[objp->instance];
int ship_index = -1;
switch (op_num)
switch (op_const)
{
case OP_FOR_SHIP_CLASS:
ship_index = shipp->ship_info_index;
@@ -10126,6 +10146,9 @@ int eval_for_ship_collection(int arg_handler_node, int condition_node, int op_nu
}
}
if (just_count)
return static_cast<int>(argument_vector.size());
// test the whole argument vector
num_valid_arguments = test_argument_vector_for_condition(argument_vector, true, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
@@ -10139,7 +10162,7 @@ int eval_for_ship_collection(int arg_handler_node, int condition_node, int op_nu
}
// Goober5000
int eval_for_players(int arg_handler_node, int condition_node)
int eval_for_players(int arg_handler_node, int condition_node, bool just_count = false)
{
int num_valid_arguments, num_true, num_false, num_known_true, num_known_false;
SCP_vector<std::pair<char*, int>> argument_vector;
@@ -10162,6 +10185,9 @@ int eval_for_players(int arg_handler_node, int condition_node)
argument_vector.emplace_back(vm_strdup(Player_ship->ship_name), -1);
}
if (just_count)
return static_cast<int>(argument_vector.size());
// test the whole argument vector
num_valid_arguments = test_argument_vector_for_condition(argument_vector, true, condition_node, &num_true, &num_false, &num_known_true, &num_known_false);
@@ -10212,7 +10238,7 @@ void sexp_change_all_argument_validity(int n, bool invalidate)
arg_handler = get_handler_for_x_of_operator(n);
// thanks to woutersmits for finding this loophole
// prevent a crash if the SEXP is used somewhere it's not supposed to be
if (arg_handler < 0)
return;
@@ -10248,6 +10274,27 @@ int sexp_num_valid_arguments( int n )
arg_handler = get_handler_for_x_of_operator(n);
// prevent a crash if the SEXP is used somewhere it's not supposed to be
if (arg_handler < 0)
return 0;
// the for-* sexps require special handling: they don't list their arguments explicitly but rather generate them on-the-fly
auto op_const = get_operator_const(arg_handler);
switch (op_const)
{
case OP_FOR_COUNTER:
return eval_for_counter(arg_handler, Locked_sexp_true, true);
case OP_FOR_PLAYERS:
return eval_for_players(arg_handler, Locked_sexp_true, true);
case OP_FOR_SHIP_CLASS:
case OP_FOR_SHIP_TYPE:
case OP_FOR_SHIP_TEAM:
case OP_FOR_SHIP_SPECIES:
return eval_for_ship_collection(arg_handler, Locked_sexp_true, op_const, true);
}
// loop through arguments
arg_n = CDR(arg_handler);
while (arg_n != -1) {
@@ -10255,7 +10302,6 @@ int sexp_num_valid_arguments( int n )
matches++;
}
// iterate
arg_n = CDR(arg_n);
}
@@ -10271,7 +10317,8 @@ void sexp_change_argument_validity(int n, bool invalidate)
arg_handler = get_handler_for_x_of_operator(n);
// thanks to woutersmits for finding this loophole
// prevent a crash if the SEXP is used somewhere it's not supposed to be
// (thanks to woutersmits for finding this bug)
if (arg_handler < 0)
return;
@@ -13978,6 +14025,28 @@ void sexp_nebula_change_pattern(int n)
neb2_post_level_init();
}
void sexp_nebula_change_fog_color(int node)
{
if (!(The_mission.flags[Mission::Mission_Flags::Fullneb])) return;
int red, green, blue = 0;
bool is_nan, is_nan_forever;
Assert(node >= 0);
eval_nums(node, is_nan, is_nan_forever, red, green, blue);
if (is_nan || is_nan_forever)
return;
CLAMP(red, 0, 255);
CLAMP(green, 0, 255);
CLAMP(blue, 0, 255);
Neb2_fog_color[0] = (ubyte)red;
Neb2_fog_color[1] = (ubyte)green;
Neb2_fog_color[2] = (ubyte)blue;
}
/**
* End the mission.
*
@@ -17771,6 +17840,7 @@ void ship_copy_damage(ship *target_shipp, ship *source_shipp)
target_objp->hull_strength = source_objp->hull_strength;
// ...and shields
target_shipp->special_shield = source_shipp->special_shield;
target_shipp->ship_max_shield_strength = source_shipp->ship_max_shield_strength;
for (i = 0; i < MIN(target_objp->n_quadrants, source_objp->n_quadrants); i++)
target_objp->shield_quadrant[i] = source_objp->shield_quadrant[i];
@@ -24592,6 +24662,11 @@ int eval_sexp(int cur_node, int referenced_node)
sexp_val = SEXP_TRUE;
break;
case OP_NEBULA_CHANGE_FOG_COLOR:
sexp_nebula_change_fog_color(node);
sexp_val = SEXP_TRUE;
break;
case OP_END_MISSION:
sexp_end_mission(node);
sexp_val = SEXP_TRUE;
@@ -26150,15 +26225,26 @@ int get_sexp_main()
int run_sexp(const char* sexpression, bool run_eval_num, bool *is_nan_or_nan_forever)
{
char* oldMp = Mp;
int n, i, sexp_val = UNINITIALIZED;
int n, sexp_val = UNINITIALIZED;
char buf[8192];
strcpy_s(buf, sexpression);
// HACK: ! -> "
for (i = 0; i < (int)strlen(buf); i++)
if (buf[i] == '!')
buf[i]='\"';
for (auto ch = buf; *ch; ++ch)
{
// convert single ! to ", but don't convert !!
if (*ch == '!')
{
if (*(ch + 1) == '!')
++ch;
else
*ch = '\"';
}
}
// !! -> !
consolidate_double_characters(buf, '!');
Mp = buf;
@@ -26784,6 +26870,7 @@ int query_operator_return_type(int op)
case OP_TURRET_CLEAR_FORCED_TARGET:
case OP_TURRET_SET_INACCURACY:
case OP_REPLACE_TEXTURE:
case OP_NEBULA_CHANGE_FOG_COLOR:
return OPR_NULL;
case OP_AI_CHASE:
@@ -29061,6 +29148,9 @@ int query_operator_argument_type(int op, int argnum)
else
return OPF_BOOL;
case OP_NEBULA_CHANGE_FOG_COLOR:
return OPF_POSITIVE;
case OP_SCRIPT_EVAL_NUM:
case OP_SCRIPT_EVAL_BLOCK:
case OP_SCRIPT_EVAL:
@@ -30806,6 +30896,7 @@ int get_subcategory(int sexp_id)
case OP_NEBULA_CHANGE_STORM:
case OP_NEBULA_TOGGLE_POOF:
case OP_NEBULA_CHANGE_PATTERN:
case OP_NEBULA_CHANGE_FOG_COLOR:
case OP_SET_AMBIENT_LIGHT:
return CHANGE_SUBCATEGORY_BACKGROUND_AND_NEBULA;
@@ -33973,7 +34064,7 @@ SCP_vector<sexp_help_struct> Sexp_help = {
{ OP_IS_SHIP_VISIBLE, "is-ship-visible\r\n"
"\tCheck whether ship is visible on a certain ship's radar. Returns 0 - not visible, 1 - partially visible, 2 - fully visible.\r\n"
"\tNote: In multiplayer, the second argument *must* be supplied or this SEXP will always return 0.\r\n"
"\tNote: In multiplayer, the second argument *must* be supplied or this SEXP will default to the first player.\r\n"
"\tTakes 1 or 2 arguments...\r\n"
"\t1: Name of ship to check\r\n"
"\t2 (optional): Name of the viewing ship. Defaults to the player's ship in single-player mode. If this ship is not in-mission, the SEXP will return 0.\r\n" },
@@ -34818,6 +34909,14 @@ SCP_vector<sexp_help_struct> Sexp_help = {
"\t1:\tNebula background pattern to change to\r\n"
},
{ OP_NEBULA_CHANGE_FOG_COLOR, "nebula-change-fog-color\r\n"
"\tChanges the current nebula fog color\r\n\r\n"
"Takes 3 arguments...\r\n"
"\t1:\tRed (0 - 255)\r\n"
"\t2:\tGreen (0 - 255)\r\n"
"\t3:\tBlue (0 - 255)\r\n"
},
{OP_SCRIPT_EVAL_NUM, "script-eval-num\r\n"
"\tEvaluates script to return a number"
"Takes 1 argument...\r\n"
+1
View File
@@ -773,6 +773,7 @@ class waypoint_list;
#define OP_TURRET_SET_INACCURACY (0x003f | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Asteroth
#define OP_REPLACE_TEXTURE (0x0040 | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Lafiel
#define OP_NEBULA_CHANGE_FOG_COLOR (0x0041 | OP_CATEGORY_CHANGE2 | OP_NONCAMPAIGN_FLAG) // Asteroth
// defined for AI goals
#define OP_AI_CHASE (0x0000 | OP_CATEGORY_AI | OP_NONCAMPAIGN_FLAG)
+13 -6
View File
@@ -19,6 +19,9 @@
#include "render/batching.h"
#include "tracing/tracing.h"
#include "tracing/Monitor.h"
#include "nebula/neb.h"
#include "mission/missionparse.h"
#include "mod_table/mod_table.h"
using namespace particle;
@@ -38,10 +41,10 @@ namespace
static int Particles_enabled = 1;
float get_current_alpha(vec3d* pos)
float get_current_alpha(vec3d* pos, float rad)
{
float dist;
float alpha;
float alpha = 0.99999f;
const float inner_radius = 30.0f;
const float magic_num = 2.75f;
@@ -55,14 +58,18 @@ namespace
if (dist <= inner_radius)
{
// alpha per meter between the magic # and the inner radius
alpha = 0.99999f / (inner_radius - magic_num);
alpha /= (inner_radius - magic_num);
// above value times the # of meters away we are
alpha *= (dist - magic_num);
return (alpha < 0.05f) ? 0.0f : alpha;
if (alpha < 0.05f)
return 0.0f;
}
return 0.99999f;
if (The_mission.flags[Mission::Mission_Flags::Fullneb] && Neb_affects_particles)
alpha *= neb2_get_fog_visibility(pos, NEB_FOG_VISIBILITY_MULT_PARTICLE(rad));
return alpha;
}
inline int get_percent(int count)
@@ -399,7 +406,7 @@ namespace particle
}
// calculate the alpha to draw at
auto alpha = get_current_alpha(&p_pos);
auto alpha = get_current_alpha(&p_pos, part->radius);
// if it's transparent then just skip it
if (alpha <= 0.0f)
+1 -1
View File
@@ -1380,7 +1380,7 @@ void player_level_init()
Viewer_external_info.current_distance = 0.0f;
if (Chase_view_default)
if (Chase_view_default || The_mission.flags[Mission::Mission_Flags::Player_start_chase_view])
{
Viewer_mode = VM_CHASE;
}
+11 -1
View File
@@ -220,7 +220,17 @@ ADE_FUNC(isAutoselect, l_UserInterface_PilotSelect, nullptr,
"Determines if the pilot selection screen should automatically select the default user.", "boolean",
"true if autoselect is enabled, false otherwise")
{
return ade_set_args(L, "b", Cmdline_benchmark_mode);
return ade_set_args(L, "b", Cmdline_benchmark_mode || Cmdline_pilot);
}
ADE_VIRTVAR(CmdlinePilot, l_UserInterface_PilotSelect, nullptr,
"The pilot chosen from commandline, if any.", "string",
"The name if specified, nil otherwise")
{
if (Cmdline_pilot)
return ade_set_args(L, "s", Cmdline_pilot);
else
return ADE_RETURN_NIL;
}
//**********SUBLIBRARY: UserInterface/MainHall
+2 -5
View File
@@ -643,15 +643,12 @@ ADE_FUNC(rotateTurret, l_Subsystem, "vector Pos, boolean reset=false", "Rotates
return ADE_RETURN_NIL;
//Get default turret info
vec3d gpos;
model_subsystem *tp = sso->ss->system_info;
object *objp = sso->objp;
ship_get_global_turret_info(objp, tp, &gpos, nullptr);
auto pmi = model_get_instance(Ships[objp->instance].model_instance_num);
auto pm = model_get(pmi->model_num);
int ret_val = model_rotate_gun(objp, pm, pmi, tp, &pos, reset);
int ret_val = model_rotate_gun(objp, pm, pmi, sso->ss, &pos, reset);
if (ret_val)
return ADE_RETURN_TRUE;
@@ -697,7 +694,7 @@ ADE_FUNC(getFOVs, l_Subsystem, nullptr, "Returns current turrets FOVs", "number,
fov = tp->turret_fov;
fov_e = tp->turret_max_fov;
fov_y = tp->turret_y_fov;
fov_y = tp->turret_base_fov;
return ade_set_args(L, "fff", fov, fov_e, fov_y);
}
+10
View File
@@ -231,6 +231,11 @@ ADE_VIRTVAR(HomingPosition, l_Weapon, "vector", "Position that weapon will home
{
wp->homing_pos = vmd_zero_vector;
}
// need to update the position for multiplayer.
if (Game_mode & GM_MULTIPLAYER) {
wp->weapon_flags.set(Weapon::Weapon_Flags::Multi_homing_update_needed);
}
}
return ade_set_args(L, "o", l_Vector.Set(wp->homing_pos));
@@ -269,6 +274,11 @@ ADE_VIRTVAR(HomingSubsystem, l_Weapon, "subsystem", "Subsystem that weapon will
wp->homing_pos = vmd_zero_vector;
wp->homing_subsys = NULL;
}
// need to update the position for multiplayer.
if (Game_mode & GM_MULTIPLAYER) {
wp->weapon_flags.set(Weapon::Weapon_Flags::Multi_homing_update_needed);
}
}
return ade_set_args(L, "o", l_Subsystem.Set(ship_subsys_h(wp->homing_object, wp->homing_subsys)));
+2
View File
@@ -19,6 +19,7 @@
#include "scripting/doc_json.h"
#include "scripting/scripting_doc.h"
#include "ship/ship.h"
#include "tracing/tracing.h"
#include "weapon/beam.h"
#include "weapon/weapon.h"
@@ -672,6 +673,7 @@ void script_state::UnloadImages()
int script_state::RunCondition(int action, object* objp, int more_data)
{
TRACE_SCOPE(tracing::LuaHooks);
int num = 0;
if (LuaState == nullptr) {
+10 -4
View File
@@ -25,6 +25,7 @@
#include "species_defs/species_defs.h"
#include "tracing/Monitor.h"
#include "tracing/tracing.h"
#include "nebula/neb.h"
int Show_shield_mesh = 0;
@@ -490,18 +491,23 @@ void render_shield(int shield_num)
float alpha = 0.9999f;
if(The_mission.flags[Mission::Mission_Flags::Fullneb]){
alpha *= 0.85f;
alpha *= neb2_get_fog_visibility(centerp, NEB_FOG_VISIBILITY_MULT_SHIELD);
}
ubyte r, g, b;
r = (ubyte)(Shield_hits[shield_num].rgb[0] * alpha);
g = (ubyte)(Shield_hits[shield_num].rgb[1] * alpha);
b = (ubyte)(Shield_hits[shield_num].rgb[2] * alpha);
if ( bitmap_id <= -1 ) {
return;
}
if ( (Detail.shield_effects == 1) || (Detail.shield_effects == 2) ) {
shield_render_low_detail_bitmap(bitmap_id, alpha, &Global_tris[Shield_hits[shield_num].tri_list[0]], orient, centerp, Shield_hits[shield_num].rgb[0], Shield_hits[shield_num].rgb[1], Shield_hits[shield_num].rgb[2]);
shield_render_low_detail_bitmap(bitmap_id, alpha, &Global_tris[Shield_hits[shield_num].tri_list[0]], orient, centerp, r, g, b);
} else if ( Detail.shield_effects < 4 ) {
for ( int i = 0; i < Shield_hits[shield_num].num_tris; i++ ) {
shield_render_triangle(bitmap_id, alpha, &Global_tris[Shield_hits[shield_num].tri_list[i]], orient, centerp, Shield_hits[shield_num].rgb[0], Shield_hits[shield_num].rgb[1], Shield_hits[shield_num].rgb[2]);
shield_render_triangle(bitmap_id, alpha, &Global_tris[Shield_hits[shield_num].tri_list[i]], orient, centerp, r, g, b);
}
} else {
float hit_radius = pm->core_radius;
@@ -510,7 +516,7 @@ void render_shield(int shield_num)
}
color clr;
gr_init_alphacolor(&clr, Shield_hits[shield_num].rgb[0], Shield_hits[shield_num].rgb[1], Shield_hits[shield_num].rgb[2], fl2i(alpha * 255.0f));
gr_init_alphacolor(&clr, r, g, b, fl2i(alpha * 255.0f));
shield_render_decal(pm, orient, centerp, &Shield_hits[shield_num].hit_orient, &Shield_hits[shield_num].hit_pos, hit_radius, bitmap_id, &clr);
}
}
+21 -4
View File
@@ -351,6 +351,7 @@ flag_def_list_new<Info_Flags> Ship_flags[] = {
{ "don't clamp max velocity", Info_Flags::Dont_clamp_max_velocity, true, false },
{ "instantaneous acceleration", Info_Flags::Instantaneous_acceleration, true, false },
{ "large ship deathroll", Info_Flags::Large_ship_deathroll, true, false },
{ "no impact debris", Info_Flags::No_impact_debris, true, false },
// to keep things clean, obsolete options go last
{ "ballistic primaries", Info_Flags::Ballistic_primaries, false, false }
};
@@ -2653,6 +2654,8 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool
if (optional_string("$Alt name:") || optional_string("$Display Name:"))
{
stuff_string(sip->display_name, F_NAME, NAME_LENGTH);
end_string_at_first_hash_symbol(sip->display_name, true);
consolidate_double_characters(sip->display_name, '#');
sip->flags.set(Ship::Info_Flags::Has_display_name);
}
@@ -4815,7 +4818,7 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool
stuff_int(&value);
CAP(value, 0, 359);
float angle = fl_radians(value)/2.0f;
sp->turret_y_fov = cosf(angle);
sp->turret_base_fov = cosf(angle);
turret_has_base_fov = true;
}
@@ -4914,7 +4917,7 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool
}
if (turret_has_base_fov)
sp->flags.set(Model::Subsystem_Flags::Turret_alt_math);
sp->flags.set(Model::Subsystem_Flags::Turret_restricted_fov);
if (optional_string("+non-targetable")) {
Warning(LOCATION, "Grammar error in table file. Please change \"+non-targetable\" to \"+untargetable\".");
@@ -5206,6 +5209,7 @@ static void parse_ship_type(const char *filename, const bool replace)
create_if_not_found = false;
}
bool first_time;
int idx = ship_type_name_lookup(name_buf);
if (idx >= 0)
{
@@ -5218,6 +5222,7 @@ static void parse_ship_type(const char *filename, const bool replace)
return;
}
stp = &Ship_types[idx];
first_time = false;
}
else
{
@@ -5231,6 +5236,7 @@ static void parse_ship_type(const char *filename, const bool replace)
Ship_types.push_back(ship_type_info());
stp = &Ship_types.back();
strcpy_s(stp->name, name_buf);
first_time = true;
}
const char *ship_type = NULL;
@@ -5250,6 +5256,15 @@ static void parse_ship_type(const char *filename, const bool replace)
Warning(LOCATION, "Bad ship type name in %s\n\nUsed ship type is redirected to another ship type.\nReplace \"%s\" with \"%s\"\nin %s to fix this.\n", filename, stp->name, ship_type, filename);
}
bool big_ship = false;
bool huge_ship = false;
if (stricmp(stp->name, "cruiser") == 0 || stricmp(stp->name, "freighter") == 0 || stricmp(stp->name, "transport") == 0 ||
stricmp(stp->name, "corvette") == 0 || stricmp(stp->name, "gas miner") == 0 || stricmp(stp->name, "awacs") == 0)
big_ship = true;
if (stricmp(stp->name, "capital") == 0 || stricmp(stp->name, "super cap") == 0 || stricmp(stp->name, "knossos device") == 0 || stricmp(stp->name, "drydock") == 0)
huge_ship = true;
//Okay, now we should have the values to parse
//But they aren't here!! :O
//Now they are!! Whee fogging!!
@@ -5414,6 +5429,8 @@ static void parse_ship_type(const char *filename, const bool replace)
if (optional_string("+Targeted by 'Huge' weapons and Ignored by 'small only' weapons:")) {
stuff_boolean_flag(stp->flags, Ship::Type_Info_Flags::Targeted_by_huge_Ignored_by_small_only);
} else if (first_time && (big_ship || huge_ship)) {
stp->flags.set(Ship::Type_Info_Flags::Targeted_by_huge_Ignored_by_small_only);
}
}
@@ -19687,8 +19704,8 @@ void ship_render(object* obj, model_draw_list* scene)
if ( !( shipp->flags[Ship_Flags::Cloaked] ) ) {
if ( ( The_mission.flags[Mission::Mission_Flags::Fullneb] ) && ( sip->is_small_ship() ) ) {
// force detail levels
float fog_val = neb2_get_fog_intensity(obj);
if ( fog_val >= 0.6f ) {
float fog_val = neb2_get_fog_visibility(obj);
if ( fog_val <= 0.15f ) {
render_info.set_detail_level_lock(2);
}
}
+1 -1
View File
@@ -1765,7 +1765,7 @@ void ship_get_global_turret_info(const object *objp, const model_subsystem *tp,
// return 1 if objp is in fov of the specified turret, tp. Otherwise return 0.
// dist = distance from turret to center point of object
int object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist);
bool object_in_turret_fov(object *objp, ship_subsys *ss, vec3d *tvec, vec3d *tpos, float dist);
// functions for testing fov.. returns true if fov test is passed.
bool turret_std_fov_test(ship_subsys *ss, vec3d *gvec, vec3d *v2e, float size_mod = 0);
+1
View File
@@ -198,6 +198,7 @@ namespace Ship {
Instantaneous_acceleration, // Goober5000
Has_display_name, // Goober5000
Large_ship_deathroll, // Asteroth - big ships dont normally deathroll, this makes them do it!
No_impact_debris, // wookieejedi - Don't spawn the small debris on impact
NUM_VALUES
};
+24 -17
View File
@@ -517,7 +517,8 @@ float do_subobj_hit_stuff(object *ship_objp, object *other_obj, vec3d *hitpos, i
if (!global_damage) {
auto subsys = ship_get_subsys_for_submodel(ship_p, submodel_num);
if (subsys == nullptr || !subsys->system_info->flags[Model::Subsystem_Flags::No_impact_debris]) {
if ( !(Ship_info[ship_p->ship_info_index].flags[Ship::Info_Flags::No_impact_debris]) &&
( subsys == nullptr || !(subsys->system_info->flags[Model::Subsystem_Flags::No_impact_debris]) ) ) {
create_generic_debris(ship_objp, hitpos, 1.0f, 5.0f, 1.0f, false);
}
}
@@ -802,30 +803,36 @@ static void shiphit_record_player_killer(object *killer_objp, player *p)
case OBJ_WEAPON:
p->killer_objtype=OBJ_WEAPON;
p->killer_weapon_index=Weapons[killer_objp->instance].weapon_info_index;
p->killer_species = Ship_info[Ships[Objects[killer_objp->parent].instance].ship_info_index].species;
if (killer_objp->parent >= 0 && killer_objp->parent < MAX_OBJECTS) {
p->killer_species = Ship_info[Ships[Objects[killer_objp->parent].instance].ship_info_index].species;
if ( &Objects[killer_objp->parent] == Player_obj ) {
// killed by a missile?
if(Weapon_info[p->killer_weapon_index].subtype == WP_MISSILE){
p->flags |= PLAYER_FLAGS_KILLED_SELF_MISSILES;
} else {
p->flags |= PLAYER_FLAGS_KILLED_SELF_UNKNOWN;
if ( &Objects[killer_objp->parent] == Player_obj ) {
// killed by a missile?
if(Weapon_info[p->killer_weapon_index].subtype == WP_MISSILE){
p->flags |= PLAYER_FLAGS_KILLED_SELF_MISSILES;
} else {
p->flags |= PLAYER_FLAGS_KILLED_SELF_UNKNOWN;
}
}
}
// in multiplayer, record callsign of killer if killed by another player
if ( (Game_mode & GM_MULTIPLAYER) && ( Objects[killer_objp->parent].flags[Object::Object_Flags::Player_ship]) ) {
int pnum;
// in multiplayer, record callsign of killer if killed by another player
if ( (Game_mode & GM_MULTIPLAYER) && ( Objects[killer_objp->parent].flags[Object::Object_Flags::Player_ship]) ) {
int pnum;
pnum = multi_find_player_by_object( &Objects[killer_objp->parent] );
if ( pnum != -1 ) {
strcpy_s(p->killer_parent_name, Net_players[pnum].m_player->callsign);
pnum = multi_find_player_by_object( &Objects[killer_objp->parent] );
if ( pnum != -1 ) {
strcpy_s(p->killer_parent_name, Net_players[pnum].m_player->callsign);
} else {
nprintf(("Network", "Couldn't find player object of weapon for killer of %s\n", p->callsign));
}
} else {
nprintf(("Network", "Couldn't find player object of weapon for killer of %s\n", p->callsign));
strcpy_s(p->killer_parent_name, Ships[Objects[killer_objp->parent].instance].get_display_name());
}
} else {
strcpy_s(p->killer_parent_name, Ships[Objects[killer_objp->parent].instance].get_display_name());
p->killer_species = -1;
strcpy_s(p->killer_parent_name, "");
}
break;
case OBJ_SHOCKWAVE:
+2
View File
@@ -124,6 +124,8 @@ add_file_folder("CFile"
cfile/cfilelist.cpp
cfile/cfilesystem.cpp
cfile/cfilesystem.h
cfile/cfilecompression.cpp
cfile/cfilecompression.h
)
# Cmdline files
+1
View File
@@ -13,6 +13,7 @@ bool Category::usesGPUCounter() const {
}
Category LuaOnFrame("LUA On Frame", true);
Category LuaHooks("LUA hooks", true);
Category DrawSceneTexture("Draw scene texture", true);
Category UpdateDistortion("Update distortion", true);
+1
View File
@@ -26,6 +26,7 @@ class Category {
};
extern Category LuaOnFrame;
extern Category LuaHooks;
extern Category DrawSceneTexture;
extern Category UpdateDistortion;
+84
View File
@@ -156,4 +156,88 @@ size_t encoded_size(codepoint_t cp) {
return 1;
}
}
bool string_is_ascii_only(const char* str, size_t len) {
for (size_t i = 0; i < len; i++) {
if (str[i] > 0x79 || str[i] < 0)
return false;
}
return true;
}
const char* get_encoding_string(Encoding encoding) {
switch (encoding) {
case Encoding::Encoding_iso8859_1:
return "ISO-8859-1";
case Encoding::Encoding_utf8:
return "UTF-8";
case Encoding::Encoding_current:
default:
UNREACHABLE("Unknown encoding type was passed.\n");
return "";
}
}
bool convert_encoding(SCP_string& buffer, const char* src, Encoding encoding_src, Encoding encoding_dest) {
if (encoding_src == Encoding::Encoding_current)
encoding_src = Unicode_text_mode ? Encoding::Encoding_utf8 : Encoding::Encoding_iso8859_1;
if (encoding_dest == Encoding::Encoding_current)
encoding_dest = Unicode_text_mode ? Encoding::Encoding_utf8 : Encoding::Encoding_iso8859_1;
//We are already in the correct encoding, the string is correct
if (encoding_src == encoding_dest) {
buffer.assign(src);
return true;
}
//If not, convert
auto len = strlen(src);
// Validate if no change needs to be done
if (string_is_ascii_only(src, len))
{
// turns out this is valid anyways
buffer.assign(src);
return true;
}
size_t newlen = len;
std::unique_ptr<char[]> newstr(new char[newlen]);
do {
auto in_str = src;
auto in_size = len;
auto out_str = newstr.get();
auto out_size = newlen;
auto iconv = SDL_iconv_open(get_encoding_string(encoding_dest), get_encoding_string(encoding_src));
auto err = SDL_iconv(iconv, &in_str, &in_size, &out_str, &out_size);
SDL_iconv_close(iconv);
// SDL returns the number of processed character on success;
// error codes are (size_t)-1 through -4
if (err < (size_t)-100)
{
// successful re-encoding
buffer.assign(newstr.get(), newlen - out_size);
return true;
}
else if (err == SDL_ICONV_E2BIG)
{
// buffer is not big enough, try again with a bigger buffer. Use a rather conservative size
// increment since the additional size required is probably pretty small
newlen += 10;
newstr.reset(new char[newlen]);
}
else
{
break;
}
} while (true);
return false;
}
}
+5
View File
@@ -163,4 +163,9 @@ void advance(octet_iterator& start, size_t n, octet_iterator end) {
}
}
enum class Encoding { Encoding_current, Encoding_utf8, Encoding_iso8859_1 };
bool string_is_ascii_only(const char* str, size_t len);
const char* get_encoding_string(Encoding encoding);
bool convert_encoding(SCP_string& buffer, const char* src, Encoding encoding_src, Encoding encoding_dest = Encoding::Encoding_current);
}
+29 -10
View File
@@ -26,6 +26,7 @@
#include "lighting/lighting.h"
#include "math/fvi.h"
#include "math/staticrand.h"
#include "nebula/neb.h"
#include "mod_table/mod_table.h"
#include "network/multi.h"
#include "network/multimsgs.h"
@@ -1351,8 +1352,21 @@ void beam_render(beam *b, float u_offset)
framenum = bm_get_anim_frame(bwsi->texture.first_frame, b->beam_section_frame[s_idx], bwsi->texture.total_time, true);
}
float fade = 0.9999f;
if (The_mission.flags[Mission::Mission_Flags::Fullneb] && Neb_affects_beams) {
vec3d nearest;
int result = vm_vec_dist_to_line(&Eye_position, &b->last_start, &b->last_shot, &nearest, nullptr);
if (result == 1)
nearest = b->last_shot;
if (result == -1)
nearest = b->last_start;
fade *= neb2_get_fog_visibility(&nearest, NEB_FOG_VISIBILITY_MULT_BEAM(b->beam_light_width));
}
material material_params;
material_set_unlit_emissive(&material_params, bwsi->texture.first_frame + framenum, 0.9999f, 2.0f);
material_set_unlit_emissive(&material_params, bwsi->texture.first_frame + framenum, fade, 2.0f);
g3_render_primitives_colored_textured(&material_params, h1, 4, PRIM_TYPE_TRIFAN, false);
}
@@ -1437,30 +1451,35 @@ void beam_generate_muzzle_particles(beam *b)
}
}
static float get_current_alpha(vec3d *pos)
static float get_muzzle_glow_alpha(beam* b)
{
float dist;
float alpha;
float alpha = 0.8f;
const float inner_radius = 15.0f;
const float magic_num = 2.75f;
// determine what alpha to draw this bitmap with
// higher alpha the closer the bitmap gets to the eye
dist = vm_vec_dist_quick(&Eye_position, pos);
dist = vm_vec_dist_quick(&Eye_position, &b->last_start);
// if the point is inside the inner radius, alpha is based on distance to the player's eye,
// becoming more transparent as it gets close
if (dist <= inner_radius) {
// alpha per meter between the magic # and the inner radius
alpha = 0.8f / (inner_radius - magic_num);
alpha /= (inner_radius - magic_num);
// above value times the # of meters away we are
alpha *= (dist - magic_num);
return (alpha < 0.005f) ? 0.0f : alpha;
if (alpha < 0.005f)
return 0.0f;
}
return 0.8f;
if (The_mission.flags[Mission::Mission_Flags::Fullneb] && Neb_affects_beams) {
alpha *= neb2_get_fog_visibility(&b->last_start, NEB_FOG_VISIBILITY_MULT_B_MUZZLE(b->beam_light_width));
}
return alpha;
}
// render the muzzle glow for a beam weapon
@@ -1507,7 +1526,7 @@ void beam_render_muzzle_glow(beam *b)
if (rad <= 0.0f)
return;
float alpha = get_current_alpha(&b->last_start);
float alpha = get_muzzle_glow_alpha(b);
if (alpha <= 0.0f)
return;
@@ -3567,9 +3586,9 @@ int beam_ok_to_fire(beam *b)
if (b->flags & BF_IS_FIGHTER_BEAM) {
turret_normal = b->objp->orient.vec.fvec;
b->subsys->system_info->flags.remove(Model::Subsystem_Flags::Turret_alt_math);
b->subsys->system_info->flags.remove(Model::Subsystem_Flags::Turret_restricted_fov);
} else {
model_instance_find_world_dir(&turret_normal, &b->subsys->system_info->turret_norm, Ships[b->objp->instance].model_instance_num, b->subsys->system_info->subobj_num, &b->objp->orient);
model_instance_find_world_dir(&turret_normal, &b->subsys->system_info->turret_norm, Ships[b->objp->instance].model_instance_num, b->subsys->system_info->subobj_num, &b->objp->orient, true);
}
if (!(turret_fov_test(b->subsys, &turret_normal, &aim_dir))) {
+7 -1
View File
@@ -13,6 +13,7 @@
#include "globalincs/linklist.h"
#include "io/timer.h"
#include "model/modelrender.h"
#include "nebula/neb.h"
#include "object/object.h"
#include "options/Option.h"
#include "render/3d.h"
@@ -392,6 +393,11 @@ void shockwave_render(object *objp, model_draw_list *scene)
if ( (sw->current_bitmap < 0) && (sw->model_id < 0) )
return;
float alpha = 1.0f;
if (The_mission.flags[Mission::Mission_Flags::Fullneb] && Neb_affects_weapons)
alpha *= neb2_get_fog_visibility(&objp->pos, NEB_FOG_VISIBILITY_MULT_SHOCKWAVE);
if (sw->model_id > -1) {
vec3d scale;
scale.xyz.x = scale.xyz.y = scale.xyz.z = sw->radius / 50.0f;
@@ -422,7 +428,7 @@ void shockwave_render(object *objp, model_draw_list *scene)
batching_add_distortion_bitmap_rotated(sw->current_bitmap, &p, fl_radians(sw->rot_angles.p), sw->radius, intensity);
}
batching_add_volume_bitmap_rotated(sw->current_bitmap, &p, fl_radians(sw->rot_angles.p), sw->radius);
batching_add_volume_bitmap_rotated(sw->current_bitmap, &p, fl_radians(sw->rot_angles.p), sw->radius, alpha);
}
}
+5
View File
@@ -13,6 +13,8 @@
#include "globalincs/systemvars.h"
#include "graphics/2d.h"
#include "io/timer.h"
#include "mission/missionparse.h"
#include "nebula/neb.h"
#include "render/3d.h"
#include "ship/ship.h"
#include "tracing/tracing.h"
@@ -224,6 +226,9 @@ void trail_render( trail * trailp )
l = (ubyte)fl2i((fade * a_size + ti->a_start) * 255.0f);
}
if (The_mission.flags[Mission::Mission_Flags::Fullneb])
l = (ubyte)(l * neb2_get_fog_visibility(&trailp->pos[n], NEB_FOG_VISIBILITY_MULT_TRAIL));
if ( i == 0 ) {
if ( num_sections > 1 ) {
vm_vec_sub(&tmp_fvec, &trailp->pos[n], &trailp->pos[sections[i+1]] );
+3
View File
@@ -344,6 +344,9 @@ struct weapon_info
float weapon_range; // max range weapon can be effectively fired. (May be less than life * speed)
float WeaponMinRange; // *Minimum weapon range, default is 0 -Et1
bool pierce_objects;
bool spawn_children_on_pierce;
// spawn weapons
int num_spawn_weapons_defined;
int maximum_children_spawned; // An upper bound for the total number of spawned children, used by multi
+2 -1
View File
@@ -99,9 +99,10 @@ namespace Weapon {
Locked_when_fired, // fired with a lock
Destroyed_by_weapon, // destroyed by damage from other weapon
Spawned, //Spawned from a spawning type weapon
Homing_update_needed, // this is a newly spawned homing weapon which needs to update client machines
No_homing, // this weapon should ignore any homing behavior it'd usually have
Overridden_homing, // Homing is overridden by an external source (probably scripting)
Multi_homing_update_needed, // this is a newly spawned homing weapon which needs to update client machines
Multi_Update_Sent, // Marks this missile as already being updated once by the server
NUM_VALUES
};
+92 -49
View File
@@ -28,6 +28,7 @@
#include "math/staticrand.h"
#include "missionui/missionweaponchoice.h"
#include "mod_table/mod_table.h"
#include "nebula/neb.h"
#include "network/multi.h"
#include "network/multimsgs.h"
#include "network/multiutil.h"
@@ -894,7 +895,8 @@ int parse_weapon(int subtype, bool replace, const char *filename)
// if this name has a hash, create a default display name
if (get_pointer_to_first_hash_symbol(wip->name)) {
strcpy_s(wip->display_name, wip->name);
end_string_at_first_hash_symbol(wip->display_name);
end_string_at_first_hash_symbol(wip->display_name, true);
consolidate_double_characters(wip->display_name, '#');
wip->wi_flags.set(Weapon::Info_Flags::Has_display_name);
preset_wi_flags.set(Weapon::Info_Flags::Has_display_name);
}
@@ -1754,6 +1756,14 @@ int parse_weapon(int subtype, bool replace, const char *filename)
}
}
if (optional_string("$Pierce Objects:")) {
stuff_boolean(&wip->pierce_objects);
if (optional_string("+Spawn Children On Pierce:")) {
stuff_boolean(&wip->spawn_children_on_pierce);
}
}
parse_wi_flags(wip, preset_wi_flags);
// preset_wi_flags does not need to be maintained after the above function is called
@@ -4484,10 +4494,6 @@ void weapon_home(object *obj, int num, float frame_time)
return;
}
}
else if (MULTIPLAYER_MASTER && (wip->is_locked_homing()) && (wp->weapon_flags[Weapon::Weapon_Flags::Homing_update_needed])) {
wp->weapon_flags.remove(Weapon::Weapon_Flags::Homing_update_needed);
send_homing_weapon_info(num);
}
if (wip->acceleration_time > 0.0f) {
if (Missiontime - wp->creation_time < fl2f(wip->acceleration_time)) {
@@ -4703,7 +4709,8 @@ void weapon_home(object *obj, int num, float frame_time)
if (hobjp->radius < 40.0f) {
target_pos = hobjp->pos;
wp->homing_pos = target_pos;
} else if (pick_homing_point || (dist < 500.0f) || (rand_chance(flFrametime, 2.0f))) {
// only recalculate a homing point if you are not a client. You will get the new point from the server.
} else if (pick_homing_point || (!MULTIPLAYER_CLIENT && ((dist < 500.0f) || (rand_chance(flFrametime, 2.0f))))) {
if (hobjp->type == OBJ_SHIP) {
if (!pick_homing_point) {
@@ -4871,8 +4878,24 @@ void weapon_update_missiles(object* obj, float frame_time) {
// a single player or multiplayer server function -- it affects actual weapon movement.
if (wip->is_homing() && !(wp->weapon_flags[Weapon::Weapon_Flags::No_homing])) {
vec3d pos_hold = wp->homing_pos;
int target_hold = wp->target_sig;
weapon_home(obj, obj->instance, frame_time);
// tell the server to send an update of the missile.
if (MULTIPLAYER_MASTER && !IS_VEC_NULL(&wp->homing_pos)) {
wp->weapon_flags.set(Weapon::Weapon_Flags::Multi_homing_update_needed);
// if the first update for a weapon has already been sent, then we do not need to send any others unless the homing_pos
// drastically changes.
if (wp->weapon_flags[Weapon::Weapon_Flags::Multi_Update_Sent]) {
vm_vec_sub2(&pos_hold, &wp->homing_pos);
if ((vm_vec_mag(&pos_hold) < 1.0f) && (wp->target_sig == target_hold)) {
wp->weapon_flags.remove(Weapon::Weapon_Flags::Multi_homing_update_needed);
}
}
}
// If this is a swarm type missile,
if (wp->swarm_info_ptr != nullptr) {
swarm_update_direction(obj, wp->swarm_info_ptr.get());
@@ -5133,9 +5156,14 @@ void weapon_process_post(object * obj, float frame_time)
if ( wp->lifeleft < 0.0f ) {
if ( wip->subtype & WP_MISSILE ) {
if(Game_mode & GM_MULTIPLAYER){
if ( !MULTIPLAYER_CLIENT || (MULTIPLAYER_CLIENT && (wp->lifeleft < -2.0f)) || (MULTIPLAYER_CLIENT && (wip->wi_flags[Weapon::Info_Flags::Child]))) { // don't call this function multiplayer client -- host will send this packet to us
if ( !MULTIPLAYER_CLIENT || (MULTIPLAYER_CLIENT && (wip->wi_flags[Weapon::Info_Flags::Child]))) { // don't call this function multiplayer client -- host will send this packet to us
weapon_detonate(obj);
}
if (MULTIPLAYER_MASTER) {
send_missile_kill_packet(obj);
}
} else {
weapon_detonate(obj);
}
@@ -5145,9 +5173,12 @@ void weapon_process_post(object * obj, float frame_time)
} else {
obj->flags.set(Object::Object_Flags::Should_be_dead);
}
return;
}
else if ((MULTIPLAYER_MASTER) && (wip->is_locked_homing() && wp->weapon_flags[Weapon::Weapon_Flags::Multi_homing_update_needed])) {
send_homing_weapon_info(obj->instance);
wp->weapon_flags.remove(Weapon::Weapon_Flags::Multi_homing_update_needed);
}
// plot homing missiles on the radar
if (((wip->wi_flags[Weapon::Info_Flags::Bomb]) || (wip->wi_flags[Weapon::Info_Flags::Shown_on_radar])) && !(wip->wi_flags[Weapon::Info_Flags::Dont_show_on_radar])) {
@@ -5551,9 +5582,6 @@ void weapon_set_tracking_info(int weapon_objnum, int parent_objnum, int target_o
// put a sanity check in the color changing laser code that was broken by this code.
if (target_is_locked && (wp->target_num != -1) && (wip->is_locked_homing()) ) {
wp->lifeleft *= LOCKED_HOMING_EXTENDED_LIFE_FACTOR;
if (MULTIPLAYER_MASTER) {
wp->weapon_flags.set(Weapon::Weapon_Flags::Homing_update_needed);
}
}
ai_update_danger_weapon(target_objnum, weapon_objnum);
@@ -6817,40 +6845,6 @@ void weapon_hit( object * weapon_obj, object * other_obj, vec3d * hitpos, int qu
}
}
// For all objects that had this weapon as a target, wipe it out, forcing find of a new enemy
for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
other_objp = &Objects[so->objnum];
Assert(other_objp->instance != -1);
shipp = &Ships[other_objp->instance];
Assert(shipp->ai_index != -1);
ai_info *aip = &Ai_info[shipp->ai_index];
if (aip->target_objnum == objnum) {
set_target_objnum(aip, -1);
// If this ship had a dynamic goal of chasing this weapon, clear the dynamic goal.
if (aip->resume_goal_time != -1)
aip->active_goal = AI_GOAL_NONE;
}
if (aip->goal_objnum == objnum) {
aip->goal_objnum = -1;
aip->goal_signature = -1;
}
if (aip->guard_objnum == objnum) {
aip->guard_objnum = -1;
aip->guard_signature = -1;
}
if (aip->hitter_objnum == objnum) {
aip->hitter_objnum = -1;
}
}
weapon_obj->flags.set(Object::Object_Flags::Should_be_dead);
//Set shockwaves flag
int sw_flag = SW_WEAPON;
@@ -6892,13 +6886,53 @@ void weapon_hit( object * weapon_obj, object * other_obj, vec3d * hitpos, int qu
}
}
// spawn weapons - note the change from FS 1 multiplayer.
if (wip->wi_flags[Weapon::Info_Flags::Spawn]){
if (!((wip->wi_flags[Weapon::Info_Flags::Dont_spawn_if_shot]) && (Weapons[num].weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon]))){ // prevent spawning of children if shot down and the dont spawn if shot flag is set (DahBlount)
spawn_child_weapons(weapon_obj);
if (!wip->pierce_objects || wip->spawn_children_on_pierce || !other_obj) {
// spawn weapons - note the change from FS 1 multiplayer.
if (wip->wi_flags[Weapon::Info_Flags::Spawn]) {
if (!((wip->wi_flags[Weapon::Info_Flags::Dont_spawn_if_shot]) && (Weapons[num].weapon_flags[Weapon::Weapon_Flags::Destroyed_by_weapon]))) { // prevent spawning of children if shot down and the dont spawn if shot flag is set (DahBlount)
spawn_child_weapons(weapon_obj);
}
}
}
//No other_obj means this weapon detonates
if (wip->pierce_objects && other_obj)
return;
// For all objects that had this weapon as a target, wipe it out, forcing find of a new enemy
for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
other_objp = &Objects[so->objnum];
Assert(other_objp->instance != -1);
shipp = &Ships[other_objp->instance];
Assert(shipp->ai_index != -1);
ai_info *aip = &Ai_info[shipp->ai_index];
if (aip->target_objnum == objnum) {
set_target_objnum(aip, -1);
// If this ship had a dynamic goal of chasing this weapon, clear the dynamic goal.
if (aip->resume_goal_time != -1)
aip->active_goal = AI_GOAL_NONE;
}
if (aip->goal_objnum == objnum) {
aip->goal_objnum = -1;
aip->goal_signature = -1;
}
if (aip->guard_objnum == objnum) {
aip->guard_objnum = -1;
aip->guard_signature = -1;
}
if (aip->hitter_objnum == objnum) {
aip->hitter_objnum = -1;
}
}
weapon_obj->flags.set(Object::Object_Flags::Should_be_dead);
// decrement parent's number of active remote detonators if applicable
if (wip->wi_flags[Weapon::Info_Flags::Remote] && weapon_obj->parent >= 0 && (weapon_obj->parent < MAX_OBJECTS)) {
object* parent = &Objects[weapon_obj->parent];
@@ -7972,6 +8006,9 @@ void weapon_render(object* obj, model_draw_list *scene)
if (wip->wi_flags[Weapon::Info_Flags::Transparent])
alpha = fl2i(wp->alpha_current * 255.0f);
if (The_mission.flags[Mission::Mission_Flags::Fullneb] && Neb_affects_weapons)
alpha = (int)(alpha * neb2_get_fog_visibility(&obj->pos, NEB_FOG_VISIBILITY_MULT_WEAPON));
vec3d headp;
vm_vec_scale_add(&headp, &obj->pos, &obj->orient.vec.fvec, wip->laser_length);
@@ -8020,6 +8057,9 @@ void weapon_render(object* obj, model_draw_list *scene)
alpha = weapon_glow_alpha;
}
if (The_mission.flags[Mission::Mission_Flags::Fullneb] && Neb_affects_weapons)
alpha = (int)(alpha * neb2_get_fog_visibility(&obj->pos, NEB_FOG_VISIBILITY_MULT_WEAPON));
batching_add_laser(wip->laser_glow_bitmap.first_frame + framenum, &headp2, wip->laser_head_radius * weapon_glow_scale_f, &tailp, wip->laser_tail_radius * weapon_glow_scale_r, (c.red*alpha)/255, (c.green*alpha)/255, (c.blue*alpha)/255);
}
@@ -8259,6 +8299,9 @@ void weapon_info::reset()
// *Minimum weapon range, default is 0 -Et1
this->WeaponMinRange = 0.0f;
this->pierce_objects = false;
this->spawn_children_on_pierce = false;
this->num_spawn_weapons_defined = 0;
this->maximum_children_spawned = 0;
for (i = 0; i < MAX_SPAWN_TYPES_PER_WEAPON; i++)
+5 -2
View File
@@ -65,6 +65,7 @@ event_editor::event_editor(CWnd* pParent /*=NULL*/)
m_persona = -1;
m_wave_filename = _T("");
m_cur_msg = -1;
m_cur_msg_old = -1;
m_team = -1;
m_message_team = -1;
m_last_message_node = -1;
@@ -87,6 +88,9 @@ event_editor::event_editor(CWnd* pParent /*=NULL*/)
void event_editor::DoDataExchange(CDataExchange* pDX)
{
if (m_cur_msg >= 0)
m_cur_msg_old = m_cur_msg;
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(event_editor)
DDX_Control(pDX, IDC_EVENT_TREE, m_event_tree);
@@ -114,7 +118,6 @@ void event_editor::DoDataExchange(CDataExchange* pDX)
DDX_Check(pDX, IDC_MISSION_LOG_LAST_TRIGGER, m_log_last_trigger);
DDX_Check(pDX, IDC_MISSION_LOG_STATE_CHANGE, m_log_state_change);
// m_team == -1 maps to 2
if(m_team == -1){
m_team = MAX_TVT_TEAMS;
@@ -910,7 +913,7 @@ void event_editor::insert_handler(int old, int node)
void event_editor::save()
{
int m = m_cur_msg;
int m = (m_cur_msg >= 0) ? m_cur_msg : m_cur_msg_old;
save_event(cur_event);
save_message(m);
+1 -1
View File
@@ -92,7 +92,7 @@ public:
CString m_message_text;
int m_persona;
CString m_wave_filename;
int m_cur_msg;
int m_cur_msg, m_cur_msg_old;
int m_team;
int m_message_team;
int m_last_message_node;
+5 -3
View File
@@ -902,7 +902,9 @@ BEGIN
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,326,151,123,10
CONTROL "Player Starts under AI Control (NO MULTI)",IDC_PLAYER_START_AI,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,326,161,146,10
CONTROL "2D Mission",IDC_2D_MISSION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,326,171,123,10
CONTROL "Player Starts in Chase View",IDC_PLAYER_START_CHASE,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,326,171,146,10
CONTROL "2D Mission",IDC_2D_MISSION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,326,181,123,10
LTEXT "AI Profile",IDC_STATIC,320,229,32,8
COMBOBOX IDC_AI_PROFILE,378,226,93,140,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Mission Description",IDC_STATIC,4,260,62,8
@@ -916,8 +918,8 @@ BEGIN
CONTROL "",IDC_MAX_RESPAWN_DELAY_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,136,112,11,14
PUSHBUTTON "Sound Environment",IDC_SOUND_ENVIRONMENT_BUTTON,158,244,140,15
CONTROL "Always Show Mission Goals In Briefing",IDC_ALWAYS_SHOW_GOALS,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,326,180,142,10
CONTROL "Mission End to Mainhall",IDC_END_TO_MAINHALL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,326,190,142,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,326,191,142,10
CONTROL "Mission End to Mainhall",IDC_END_TO_MAINHALL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,326,201,142,10
CONTROL "Override #Command in event messages",IDC_OVERRIDE_HASHCOMMAND,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,166,172,142,10
END
+2
View File
@@ -1125,6 +1125,8 @@ void inc_mission_time() {
if (Frametime > MAX_FRAMETIME) {
Frametime = MAX_FRAMETIME;
} else if (Frametime < 0) {
Frametime = thistime = MIN_FRAMETIME;
} else if (Frametime < MIN_FRAMETIME) {
if (!Cmdline_NoFPSCap) {
thistime = MIN_FRAMETIME - Frametime;
+1 -1
View File
@@ -4369,7 +4369,7 @@ void CFREDView::OnUpdateDisableUndo(CCmdUI* pCmdUI)
void CFREDView::OnUpdateCmdBrief(CCmdUI* pCmdUI)
{
pCmdUI->Enable(!(The_mission.game_type & MISSION_TYPE_MULTI));
pCmdUI->Enable(true);
}
int get_visible_sub_system_count(ship *shipp)
+6
View File
@@ -67,6 +67,7 @@ CMissionNotesDlg::CMissionNotesDlg(CWnd* pParent /*=NULL*/) : CDialog(CMissionNo
m_support_repairs_hull = FALSE;
m_beam_free_all_by_default = FALSE;
m_player_start_using_ai = FALSE;
m_player_start_chase_view = FALSE;
m_no_briefing = FALSE;
m_no_debriefing = FALSE;
m_autpilot_cinematics = FALSE;
@@ -120,6 +121,7 @@ void CMissionNotesDlg::DoDataExchange(CDataExchange* pDX)
DDX_Check(pDX, IDC_SUPPORT_REPAIRS_HULL, m_support_repairs_hull);
DDX_Check(pDX, IDC_BEAM_FREE_ALL_BY_DEFAULT, m_beam_free_all_by_default);
DDX_Check(pDX, IDC_PLAYER_START_AI, m_player_start_using_ai);
DDX_Check(pDX, IDC_PLAYER_START_CHASE, m_player_start_chase_view);
DDX_Check(pDX, IDC_NO_BRIEFING, m_no_briefing);
DDX_Check(pDX, IDC_NO_DEBRIEFING, m_no_debriefing);
DDX_Check(pDX, IDC_USE_AUTOPILOT_CINEMATICS, m_autpilot_cinematics);
@@ -273,6 +275,9 @@ void CMissionNotesDlg::OnOK()
// set player AI by default
The_mission.flags.set(Mission::Mission_Flags::Player_start_ai, m_player_start_using_ai != 0);
// set player chase view
The_mission.flags.set(Mission::Mission_Flags::Player_start_chase_view, m_player_start_chase_view != 0);
// set briefing
The_mission.flags.set(Mission::Mission_Flags::No_briefing, m_no_briefing != 0);
@@ -394,6 +399,7 @@ BOOL CMissionNotesDlg::OnInitDialog()
m_support_repairs_hull = (The_mission.flags[Mission::Mission_Flags::Support_repairs_hull]) ? 1 : 0;
m_beam_free_all_by_default = (The_mission.flags[Mission::Mission_Flags::Beam_free_all_by_default]) ? 1 : 0;
m_player_start_using_ai = (The_mission.flags[Mission::Mission_Flags::Player_start_ai]) ? 1 : 0;
m_player_start_chase_view = (The_mission.flags[Mission::Mission_Flags::Player_start_chase_view]) ? 1 : 0;
m_no_briefing = (The_mission.flags[Mission::Mission_Flags::No_briefing]) ? 1 : 0;
m_no_debriefing = (The_mission.flags[Mission::Mission_Flags::Toggle_debriefing]) ? 1 : 0;
m_autpilot_cinematics = (The_mission.flags[Mission::Mission_Flags::Use_ap_cinematics]) ? 1 : 0;
+1
View File
@@ -58,6 +58,7 @@ public:
BOOL m_support_repairs_hull;
BOOL m_beam_free_all_by_default;
BOOL m_player_start_using_ai;
BOOL m_player_start_chase_view;
BOOL m_no_briefing;
BOOL m_no_debriefing;
BOOL m_autpilot_cinematics;
-3
View File
@@ -1371,9 +1371,6 @@ int CFred_mission_save::save_cmd_brief()
required_string_fred("#Command Briefing");
parse_comments(2);
if (The_mission.game_type & MISSION_TYPE_MULTI)
return err; // no command briefings allowed in multiplayer missions.
save_custom_bitmap("$Background 640:", "$Background 1024:", Cur_cmd_brief->background[GR_640], Cur_cmd_brief->background[GR_1024], 1);
for (stage = 0; stage < Cur_cmd_brief->num_stages; stage++) {
+1
View File
@@ -1054,6 +1054,7 @@
#define IDC_EXPORT 1581
#define IDC_SECONDARIES_LOCKED 1582
#define IDC_SUBSTITUTE_BRIEFING_MUSIC 1582
#define IDC_PLAYER_START_CHASE 1583
#define IDC_RESTRICT_PATHS_LABEL 1584
#define IDC_PATH_LIST 1585
#define IDC_BACKGROUND 1586
+118 -62
View File
@@ -2030,8 +2030,21 @@ void game_show_framerate()
gr_set_color_fast(&HUD_color_debug);
if (Cmdline_frame_profile) {
gr_string(gr_screen.center_offset_x + 20, gr_screen.center_offset_y + 100 + line_height,
tracing::get_frame_profile_output().c_str(), GR_RESIZE_NONE);
// Split frame profile into two columns if necessary to avoid losing trace data
int fp_start_y = gr_screen.center_offset_y + 100 + line_height;
int fp_line_limit = (gr_screen.max_h - fp_start_y) / line_height;
size_t fp_column_break = 0;
auto fp_trace_str = tracing::get_frame_profile_output();
for (int i = 0; i < fp_line_limit && fp_column_break < fp_trace_str.length(); i++) {
fp_column_break = fp_trace_str.find_first_of('\n', fp_column_break+1);
}
gr_string(gr_screen.center_offset_x + 20, fp_start_y, fp_trace_str.substr(0,fp_column_break).c_str(), GR_RESIZE_NONE);
if (fp_column_break < fp_trace_str.length()) {
gr_string(gr_screen.max_w / 2, fp_start_y, fp_trace_str.substr(fp_column_break, fp_trace_str.npos).c_str(), GR_RESIZE_NONE);
}
}
if (Show_framerate) {
@@ -4941,6 +4954,40 @@ void game_process_event( int current_state, int event )
}
}
static bool going_to_briefing_state(int new_state)
{
switch (new_state) {
case GS_STATE_TEAM_SELECT:
case GS_STATE_SHIP_SELECT:
case GS_STATE_WEAPON_SELECT:
case GS_STATE_OPTIONS_MENU:
case GS_STATE_GAMEPLAY_HELP:
case GS_STATE_HOTKEY_SCREEN:
case GS_STATE_MULTI_MISSION_SYNC:
case GS_STATE_BRIEFING:
case GS_STATE_CMD_BRIEF:
case GS_STATE_RED_ALERT:
case GS_STATE_FICTION_VIEWER:
return true;
}
return false;
}
static bool going_to_menu_state(int new_state)
{
switch (new_state) {
case GS_STATE_MAIN_MENU:
case GS_STATE_PXO:
case GS_STATE_MULTI_JOIN_GAME:
case GS_STATE_STANDALONE_MAIN:
case GS_STATE_QUIT_GAME:
return true;
}
return false;
}
// Called when a state is being left.
// The current state is still at old_state, but as soon as
// this function leaves, then the current state will become
@@ -4989,17 +5036,15 @@ void game_leave_state( int old_state, int new_state )
switch (old_state) {
case GS_STATE_BRIEFING:
brief_stop_voices();
if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
&& (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
&& (new_state != GS_STATE_TEAM_SELECT) && (new_state != GS_STATE_MULTI_MISSION_SYNC)){
if ( !going_to_briefing_state(new_state) ) {
common_select_close();
if ( (new_state == GS_STATE_MAIN_MENU) || (new_state == GS_STATE_PXO)
|| (new_state == GS_STATE_MULTI_JOIN_GAME) )
{
freespace_stop_mission();
if ( going_to_menu_state(new_state) ) {
freespace_stop_mission();
}
}
// COMMAND LINE OPTION
if (Cmdline_multi_stream_chat_to_file){
cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
@@ -5035,67 +5080,57 @@ void game_leave_state( int old_state, int new_state )
cmd_brief_hold();
} else {
cmd_brief_close();
common_select_close();
if (new_state != GS_STATE_BRIEFING) {
common_music_close();
}
if ( !going_to_briefing_state(new_state) ) {
common_select_close();
if ( (new_state == GS_STATE_MAIN_MENU) || (new_state == GS_STATE_PXO)
|| (new_state == GS_STATE_MULTI_JOIN_GAME) )
{
freespace_stop_mission();
if ( going_to_menu_state(new_state) ) {
freespace_stop_mission();
}
}
}
break;
case GS_STATE_RED_ALERT:
red_alert_close();
common_select_close();
if ( (new_state == GS_STATE_MAIN_MENU) || (new_state == GS_STATE_PXO)
|| (new_state == GS_STATE_MULTI_JOIN_GAME) )
{
freespace_stop_mission();
if ( !going_to_briefing_state(new_state) ) {
common_select_close();
if ( going_to_menu_state(new_state) ) {
freespace_stop_mission();
}
}
break;
case GS_STATE_SHIP_SELECT:
if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
new_state != GS_STATE_HOTKEY_SCREEN &&
new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT && (new_state != GS_STATE_MULTI_MISSION_SYNC)) {
if ( !going_to_briefing_state(new_state) ) {
common_select_close();
if ( (new_state == GS_STATE_MAIN_MENU) || (new_state == GS_STATE_PXO)
|| (new_state == GS_STATE_MULTI_JOIN_GAME) )
{
freespace_stop_mission();
if ( going_to_menu_state(new_state) ) {
freespace_stop_mission();
}
}
break;
case GS_STATE_WEAPON_SELECT:
if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
new_state != GS_STATE_HOTKEY_SCREEN &&
new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT && (new_state != GS_STATE_MULTI_MISSION_SYNC)) {
if ( !going_to_briefing_state(new_state) ) {
common_select_close();
if ( (new_state == GS_STATE_MAIN_MENU) || (new_state == GS_STATE_PXO)
|| (new_state == GS_STATE_MULTI_JOIN_GAME) )
{
freespace_stop_mission();
if ( going_to_menu_state(new_state) ) {
freespace_stop_mission();
}
}
break;
case GS_STATE_TEAM_SELECT:
if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
new_state != GS_STATE_HOTKEY_SCREEN &&
new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT && (new_state != GS_STATE_MULTI_MISSION_SYNC)) {
if ( !going_to_briefing_state(new_state) ) {
common_select_close();
if ( (new_state == GS_STATE_MAIN_MENU) || (new_state == GS_STATE_PXO)
|| (new_state == GS_STATE_MULTI_JOIN_GAME) )
{
freespace_stop_mission();
if ( going_to_menu_state(new_state) ) {
freespace_stop_mission();
}
}
}
break;
case GS_STATE_MAIN_MENU:
@@ -5109,6 +5144,12 @@ void game_leave_state( int old_state, int new_state )
options_menu_close();
// can't use going_to_briefing_state() here since it doesn't catch sub-optionmenu states
// it's basically just to catch the exit game button
if ( going_to_menu_state(new_state) ) {
common_select_close();
}
if (new_state != GS_STATE_CONTROL_CONFIG && new_state != GS_STATE_HUD_CONFIG) {
// unpause all sounds, since we could be headed back to the game
// only unpause if we're in-mission; we could also be in the main hall
@@ -5305,7 +5346,9 @@ void game_leave_state( int old_state, int new_state )
break;
case GS_STATE_MULTI_MISSION_SYNC:
common_select_close();
if ( !going_to_briefing_state(new_state) ) {
common_select_close();
}
// if we're moving into the options menu we don't need to do anything else
if(new_state == GS_STATE_OPTIONS_MENU){
@@ -5314,6 +5357,7 @@ void game_leave_state( int old_state, int new_state )
Assert( Game_mode & GM_MULTIPLAYER );
multi_sync_close();
if ( new_state == GS_STATE_GAME_PLAY ){
// palette_restore_palette();
@@ -5323,10 +5367,14 @@ void game_leave_state( int old_state, int new_state )
// set the game mode
Game_mode |= GM_IN_MISSION;
// any other state needs to close out the mission, because we're not going in to gameplay.
} else if ( going_to_menu_state(new_state) ) {
freespace_stop_mission();
}
main_hall_stop_music(true);
main_hall_stop_ambient();
main_hall_stop_ambient();
break;
case GS_STATE_VIEW_CUTSCENES:
@@ -5378,16 +5426,13 @@ void game_leave_state( int old_state, int new_state )
case GS_STATE_FICTION_VIEWER:
fiction_viewer_close();
common_select_close();
if ( (new_state != GS_STATE_BRIEFING) && (new_state != GS_STATE_CMD_BRIEF) ) {
common_music_close();
}
if ( !going_to_briefing_state(new_state) ) {
common_select_close();
if ( (new_state == GS_STATE_MAIN_MENU) || (new_state == GS_STATE_PXO)
|| (new_state == GS_STATE_MULTI_JOIN_GAME) )
{
freespace_stop_mission();
if ( going_to_menu_state(new_state) ) {
freespace_stop_mission();
}
}
break;
@@ -7540,13 +7585,24 @@ int main(int argc, char *argv[])
SCP_mspdbcs_Initialise();
// If we're being evoked from a console, attach the STDIO streams to it and reopen the streams
// This is needed because Windows assumes SUBSYSTEM:WINDOWS programs won't need console IO. Additionally, SDL
// seems to close or otherwise grab the streams for somthing else.
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
bool keep_stdout = false;
char envbuf[2];
// GetEnvironmentVariable returns the amount of stored characters on success, we're looking for the value "1"
// so we only care about the case where it successfully read exactly one character (not including the null byte).
if (GetEnvironmentVariable("FSO_KEEP_STDOUT", envbuf, 2) == 1) {
keep_stdout = envbuf[0] == '1';
}
// Only try redirecting stdout if FSO_KEEP_STDOUT is not set to "1".
if (!keep_stdout) {
// If we're being evoked from a console, attach the STDIO streams to it and reopen the streams
// This is needed because Windows assumes SUBSYSTEM:WINDOWS programs won't need console IO. Additionally, SDL
// seems to close or otherwise grab the streams for somthing else.
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
}
}
#else
#ifdef APPLE_APP
+2
View File
@@ -50,3 +50,5 @@ include(vulkan.cmake)
add_subdirectory(mdns)
add_subdirectory(variant)
ADD_SUBDIRECTORY(lz4)
+51
View File
@@ -0,0 +1,51 @@
IF(NOT FSO_BUILD_INCLUDED_LIBS)
FIND_PACKAGE(LZ4 QUIET)
ENDIF(NOT FSO_BUILD_INCLUDED_LIBS)
IF (FSO_BUILD_INCLUDED_LIBS OR NOT LZ4_FOUND)
MESSAGE(STATUS "Building lz4 from source")
SET(LZ4_SOURCES
lz4.c
lz4frame.c
lz4hc.c
xxhash.c
lz4.h
lz4frame.h
lz4hc.h
xxhash.h)
ADD_LIBRARY(lz4 ${LZ4_SOURCES})
target_include_directories(lz4 SYSTEM PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
set_target_properties(lz4
PROPERTIES
FOLDER "3rdparty"
DEFINE_SYMBOL LZ4_DLL # This will only be defined if we are building a shared library
)
# Disable warnings if building from source
suppress_warnings(lz4)
target_link_libraries(lz4 PUBLIC compiler)
IF(BUILD_SHARED_LIBS)
target_compile_definitions(lz4 INTERFACE LZ4_DLL)
ENDIF(BUILD_SHARED_LIBS)
IF(FSO_COPY_EXE AND BUILD_SHARED_LIBS)
INSTALL(
TARGETS lz4
RUNTIME DESTINATION ${BINARY_DESTINATION}
LIBRARY DESTINATION ${BINARY_DESTINATION}
)
ENDIF(FSO_COPY_EXE AND BUILD_SHARED_LIBS)
ELSE(FSO_BUILD_INCLUDED_LIBS OR NOT LZ4_FOUND)
INCLUDE(util)
ADD_IMPORTED_LIB(lz4 ${LZ4_INCLUDE_DIR} ${LZ4_LIBRARIES})
ENDIF(FSO_BUILD_INCLUDED_LIBS OR NOT LZ4_FOUND)
+2495
View File
File diff suppressed because it is too large. Load diff
+774
View File
@@ -0,0 +1,774 @@
/*
* LZ4 - Fast LZ compression algorithm
* Header File
* Copyright (C) 2011-2020, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 homepage : http://www.lz4.org
- LZ4 source repository : https://github.com/lz4/lz4
*/
#if defined (__cplusplus)
extern "C" {
#endif
#ifndef LZ4_H_2983827168210
#define LZ4_H_2983827168210
/* --- Dependency --- */
#include <stddef.h> /* size_t */
/**
Introduction
LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core,
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
The LZ4 compression library provides in-memory compression and decompression functions.
It gives full buffer control to user.
Compression can be done in:
- a single step (described as Simple Functions)
- a single step, reusing a context (described in Advanced Functions)
- unbounded multiple steps (described as Streaming compression)
lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).
Decompressing such a compressed block requires additional metadata.
Exact metadata depends on exact decompression function.
For the typical case of LZ4_decompress_safe(),
metadata includes block's compressed size, and maximum bound of decompressed size.
Each application is free to encode and pass such metadata in whichever way it wants.
lz4.h only handle blocks, it can not generate Frames.
Blocks are different from Frames (doc/lz4_Frame_format.md).
Frames bundle both blocks and metadata in a specified manner.
Embedding metadata is required for compressed data to be self-contained and portable.
Frame format is delivered through a companion API, declared in lz4frame.h.
The `lz4` CLI can only manage frames.
*/
/*^***************************************************************
* Export parameters
*****************************************************************/
/*
* LZ4_DLL_EXPORT :
* Enable exporting of functions when building a Windows DLL
* LZ4LIB_VISIBILITY :
* Control library symbols visibility.
*/
#ifndef LZ4LIB_VISIBILITY
# if defined(__GNUC__) && (__GNUC__ >= 4)
# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))
# else
# define LZ4LIB_VISIBILITY
# endif
#endif
#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY
#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
#else
# define LZ4LIB_API LZ4LIB_VISIBILITY
#endif
/*------ Version ------*/
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */
#define LZ4_VERSION_RELEASE 3 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
#define LZ4_QUOTE(str) #str
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION)
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version */
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; useful to check dll version */
/*-************************************
* Tuning parameter
**************************************/
/*!
* LZ4_MEMORY_USAGE :
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
* Increasing memory usage improves compression ratio.
* Reduced memory usage may improve speed, thanks to better cache locality.
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
*/
#ifndef LZ4_MEMORY_USAGE
# define LZ4_MEMORY_USAGE 14
#endif
/*-************************************
* Simple Functions
**************************************/
/*! LZ4_compress_default() :
* Compresses 'srcSize' bytes from buffer 'src'
* into already allocated 'dst' buffer of size 'dstCapacity'.
* Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
* It also runs faster, so it's a recommended setting.
* If the function cannot compress 'src' into a more limited 'dst' budget,
* compression stops *immediately*, and the function result is zero.
* In which case, 'dst' content is undefined (invalid).
* srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
* dstCapacity : size of buffer 'dst' (which must be already allocated)
* @return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
* or 0 if compression fails
* Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
*/
LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
/*! LZ4_decompress_safe() :
* compressedSize : is the exact complete size of the compressed block.
* dstCapacity : is the size of destination buffer (which must be already allocated), presumed an upper bound of decompressed size.
* @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
* If destination buffer is not large enough, decoding will stop and output an error code (negative value).
* If the source stream is detected malformed, the function will stop decoding and return a negative result.
* Note 1 : This function is protected against malicious data packets :
* it will never writes outside 'dst' buffer, nor read outside 'source' buffer,
* even if the compressed block is maliciously modified to order the decoder to do these actions.
* In such case, the decoder stops immediately, and considers the compressed block malformed.
* Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them.
* The implementation is free to send / store / derive this information in whichever way is most beneficial.
* If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead.
*/
LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
/*-************************************
* Advanced Functions
**************************************/
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
/*! LZ4_compressBound() :
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
This function is primarily useful for memory allocation purposes (destination buffer size).
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize)
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
return : maximum output size in a "worst case" scenario
or 0, if input size is incorrect (too large or negative)
*/
LZ4LIB_API int LZ4_compressBound(int inputSize);
/*! LZ4_compress_fast() :
Same as LZ4_compress_default(), but allows selection of "acceleration" factor.
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
An acceleration value of "1" is the same as regular LZ4_compress_default()
Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c).
Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c).
*/
LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_compress_fast_extState() :
* Same as LZ4_compress_fast(), using an externally allocated memory space for its state.
* Use LZ4_sizeofState() to know how much memory must be allocated,
* and allocate it on 8-bytes boundaries (using `malloc()` typically).
* Then, provide this buffer as `void* state` to compression function.
*/
LZ4LIB_API int LZ4_sizeofState(void);
LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_compress_destSize() :
* Reverse the logic : compresses as much data as possible from 'src' buffer
* into already allocated buffer 'dst', of size >= 'targetDestSize'.
* This function either compresses the entire 'src' content into 'dst' if it's large enough,
* or fill 'dst' buffer completely with as much data as possible from 'src'.
* note: acceleration parameter is fixed to "default".
*
* *srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'.
* New value is necessarily <= input value.
* @return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
* or 0 if compression fails.
*
* Note : from v1.8.2 to v1.9.1, this function had a bug (fixed un v1.9.2+):
* the produced compressed content could, in specific circumstances,
* require to be decompressed into a destination buffer larger
* by at least 1 byte than the content to decompress.
* If an application uses `LZ4_compress_destSize()`,
* it's highly recommended to update liblz4 to v1.9.2 or better.
* If this can't be done or ensured,
* the receiving decompression function should provide
* a dstCapacity which is > decompressedSize, by at least 1 byte.
* See https://github.com/lz4/lz4/issues/859 for details
*/
LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
/*! LZ4_decompress_safe_partial() :
* Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',
* into destination buffer 'dst' of size 'dstCapacity'.
* Up to 'targetOutputSize' bytes will be decoded.
* The function stops decoding on reaching this objective.
* This can be useful to boost performance
* whenever only the beginning of a block is required.
*
* @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize)
* If source stream is detected malformed, function returns a negative result.
*
* Note 1 : @return can be < targetOutputSize, if compressed block contains less data.
*
* Note 2 : targetOutputSize must be <= dstCapacity
*
* Note 3 : this function effectively stops decoding on reaching targetOutputSize,
* so dstCapacity is kind of redundant.
* This is because in older versions of this function,
* decoding operation would still write complete sequences.
* Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize,
* it could write more bytes, though only up to dstCapacity.
* Some "margin" used to be required for this operation to work properly.
* Thankfully, this is no longer necessary.
* The function nonetheless keeps the same signature, in an effort to preserve API compatibility.
*
* Note 4 : If srcSize is the exact size of the block,
* then targetOutputSize can be any value,
* including larger than the block's decompressed size.
* The function will, at most, generate block's decompressed size.
*
* Note 5 : If srcSize is _larger_ than block's compressed size,
* then targetOutputSize **MUST** be <= block's decompressed size.
* Otherwise, *silent corruption will occur*.
*/
LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
/*-*********************************************
* Streaming Compression Functions
***********************************************/
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
/*! LZ4_resetStream_fast() : v1.9.0+
* Use this to prepare an LZ4_stream_t for a new chain of dependent blocks
* (e.g., LZ4_compress_fast_continue()).
*
* An LZ4_stream_t must be initialized once before usage.
* This is automatically done when created by LZ4_createStream().
* However, should the LZ4_stream_t be simply declared on stack (for example),
* it's necessary to initialize it first, using LZ4_initStream().
*
* After init, start any new stream with LZ4_resetStream_fast().
* A same LZ4_stream_t can be re-used multiple times consecutively
* and compress multiple streams,
* provided that it starts each new stream with LZ4_resetStream_fast().
*
* LZ4_resetStream_fast() is much faster than LZ4_initStream(),
* but is not compatible with memory regions containing garbage data.
*
* Note: it's only useful to call LZ4_resetStream_fast()
* in the context of streaming compression.
* The *extState* functions perform their own resets.
* Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive.
*/
LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
/*! LZ4_loadDict() :
* Use this function to reference a static dictionary into LZ4_stream_t.
* The dictionary must remain available during compression.
* LZ4_loadDict() triggers a reset, so any previous data will be forgotten.
* The same dictionary will have to be loaded on decompression side for successful decoding.
* Dictionary are useful for better compression of small data (KB range).
* While LZ4 accept any input as dictionary,
* results are generally better when using Zstandard's Dictionary Builder.
* Loading a size of 0 is allowed, and is the same as reset.
* @return : loaded dictionary size, in bytes (necessarily <= 64 KB)
*/
LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
/*! LZ4_compress_fast_continue() :
* Compress 'src' content using data from previously compressed blocks, for better compression ratio.
* 'dst' buffer must be already allocated.
* If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
*
* @return : size of compressed block
* or 0 if there is an error (typically, cannot fit into 'dst').
*
* Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block.
* Each block has precise boundaries.
* Each block must be decompressed separately, calling LZ4_decompress_*() with relevant metadata.
* It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together.
*
* Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory !
*
* Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB.
* Make sure that buffers are separated, by at least one byte.
* This construction ensures that each block only depends on previous block.
*
* Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.
*
* Note 5 : After an error, the stream status is undefined (invalid), it can only be reset or freed.
*/
LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_saveDict() :
* If last 64KB data cannot be guaranteed to remain available at its current memory location,
* save it into a safer place (char* safeBuffer).
* This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),
* but is much faster, because LZ4_saveDict() doesn't need to rebuild tables.
* @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error.
*/
LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);
/*-**********************************************
* Streaming Decompression Functions
* Bufferless synchronous API
************************************************/
typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */
/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :
* creation / destruction of streaming decompression tracking context.
* A tracking context can be re-used multiple times.
*/
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
/*! LZ4_setStreamDecode() :
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
* Use this function to start decompression of a new stream of blocks.
* A dictionary can optionally be set. Use NULL or size 0 for a reset order.
* Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.
* @return : 1 if OK, 0 if error
*/
LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
/*! LZ4_decoderRingBufferSize() : v1.8.2+
* Note : in a ring buffer scenario (optional),
* blocks are presumed decompressed next to each other
* up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize),
* at which stage it resumes from beginning of ring buffer.
* When setting such a ring buffer for streaming decompression,
* provides the minimum size of this ring buffer
* to be compatible with any source respecting maxBlockSize condition.
* @return : minimum ring buffer size,
* or 0 if there is an error (invalid maxBlockSize).
*/
LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);
#define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize)) /* for static allocation; maxBlockSize presumed valid */
/*! LZ4_decompress_*_continue() :
* These decoding functions allow decompression of consecutive blocks in "streaming" mode.
* A block is an unsplittable entity, it must be presented entirely to a decompression function.
* Decompression functions only accepts one block at a time.
* The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded.
* If less than 64KB of data has been decoded, all the data must be present.
*
* Special : if decompression side sets a ring buffer, it must respect one of the following conditions :
* - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize).
* maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes.
* In which case, encoding and decoding buffers do not need to be synchronized.
* Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize.
* - Synchronized mode :
* Decompression buffer size is _exactly_ the same as compression buffer size,
* and follows exactly same update rule (block boundaries at same positions),
* and decoding function is provided with exact decompressed size of each block (exception for last block of the stream),
* _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB).
* - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes.
* In which case, encoding and decoding buffers do not need to be synchronized,
* and encoding ring buffer can have any size, including small ones ( < 64 KB).
*
* Whenever these conditions are not possible,
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
*/
LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity);
/*! LZ4_decompress_*_usingDict() :
* These decoding functions work the same as
* a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue()
* They are stand-alone, and don't need an LZ4_streamDecode_t structure.
* Dictionary is presumed stable : it must remain accessible and unmodified during decompression.
* Performance tip : Decompression speed can be substantially increased
* when dst == dictStart + dictSize.
*/
LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize);
#endif /* LZ4_H_2983827168210 */
/*^*************************************
* !!!!!! STATIC LINKING ONLY !!!!!!
***************************************/
/*-****************************************************************************
* Experimental section
*
* Symbols declared in this section must be considered unstable. Their
* signatures or semantics may change, or they may be removed altogether in the
* future. They are therefore only safe to depend on when the caller is
* statically linked against the library.
*
* To protect against unsafe usage, not only are the declarations guarded,
* the definitions are hidden by default
* when building LZ4 as a shared/dynamic library.
*
* In order to access these declarations,
* define LZ4_STATIC_LINKING_ONLY in your application
* before including LZ4's headers.
*
* In order to make their implementations accessible dynamically, you must
* define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.
******************************************************************************/
#ifdef LZ4_STATIC_LINKING_ONLY
#ifndef LZ4_STATIC_3504398509
#define LZ4_STATIC_3504398509
#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS
#define LZ4LIB_STATIC_API LZ4LIB_API
#else
#define LZ4LIB_STATIC_API
#endif
/*! LZ4_compress_fast_extState_fastReset() :
* A variant of LZ4_compress_fast_extState().
*
* Using this variant avoids an expensive initialization step.
* It is only safe to call if the state buffer is known to be correctly initialized already
* (see above comment on LZ4_resetStream_fast() for a definition of "correctly initialized").
* From a high level, the difference is that
* this function initializes the provided state with a call to something like LZ4_resetStream_fast()
* while LZ4_compress_fast_extState() starts with a call to LZ4_resetStream().
*/
LZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
/*! LZ4_attach_dictionary() :
* This is an experimental API that allows
* efficient use of a static dictionary many times.
*
* Rather than re-loading the dictionary buffer into a working context before
* each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a
* working LZ4_stream_t, this function introduces a no-copy setup mechanism,
* in which the working stream references the dictionary stream in-place.
*
* Several assumptions are made about the state of the dictionary stream.
* Currently, only streams which have been prepared by LZ4_loadDict() should
* be expected to work.
*
* Alternatively, the provided dictionaryStream may be NULL,
* in which case any existing dictionary stream is unset.
*
* If a dictionary is provided, it replaces any pre-existing stream history.
* The dictionary contents are the only history that can be referenced and
* logically immediately precede the data compressed in the first subsequent
* compression call.
*
* The dictionary will only remain attached to the working stream through the
* first compression call, at the end of which it is cleared. The dictionary
* stream (and source buffer) must remain in-place / accessible / unchanged
* through the completion of the first compression call on the stream.
*/
LZ4LIB_STATIC_API void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream);
/*! In-place compression and decompression
*
* It's possible to have input and output sharing the same buffer,
* for highly constrained memory environments.
* In both cases, it requires input to lay at the end of the buffer,
* and decompression to start at beginning of the buffer.
* Buffer size must feature some margin, hence be larger than final size.
*
* |<------------------------buffer--------------------------------->|
* |<-----------compressed data--------->|
* |<-----------decompressed size------------------>|
* |<----margin---->|
*
* This technique is more useful for decompression,
* since decompressed size is typically larger,
* and margin is short.
*
* In-place decompression will work inside any buffer
* which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize).
* This presumes that decompressedSize > compressedSize.
* Otherwise, it means compression actually expanded data,
* and it would be more efficient to store such data with a flag indicating it's not compressed.
* This can happen when data is not compressible (already compressed, or encrypted).
*
* For in-place compression, margin is larger, as it must be able to cope with both
* history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX,
* and data expansion, which can happen when input is not compressible.
* As a consequence, buffer size requirements are much higher,
* and memory savings offered by in-place compression are more limited.
*
* There are ways to limit this cost for compression :
* - Reduce history size, by modifying LZ4_DISTANCE_MAX.
* Note that it is a compile-time constant, so all compressions will apply this limit.
* Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX,
* so it's a reasonable trick when inputs are known to be small.
* - Require the compressor to deliver a "maximum compressed size".
* This is the `dstCapacity` parameter in `LZ4_compress*()`.
* When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail,
* in which case, the return code will be 0 (zero).
* The caller must be ready for these cases to happen,
* and typically design a backup scheme to send data uncompressed.
* The combination of both techniques can significantly reduce
* the amount of margin required for in-place compression.
*
* In-place compression can work in any buffer
* which size is >= (maxCompressedSize)
* with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success.
* LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX,
* so it's possible to reduce memory requirements by playing with them.
*/
#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize) (((compressedSize) >> 8) + 32)
#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize) ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize)) /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */
#ifndef LZ4_DISTANCE_MAX /* history window size; can be user-defined at compile time */
# define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */
#endif
#define LZ4_COMPRESS_INPLACE_MARGIN (LZ4_DISTANCE_MAX + 32) /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */
#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize) ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN) /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */
#endif /* LZ4_STATIC_3504398509 */
#endif /* LZ4_STATIC_LINKING_ONLY */
#ifndef LZ4_H_98237428734687
#define LZ4_H_98237428734687
/*-************************************************************
* Private Definitions
**************************************************************
* Do not use these definitions directly.
* They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
* Accessing members will expose user code to API and/or ABI break in future versions of the library.
**************************************************************/
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
# include <stdint.h>
typedef int8_t LZ4_i8;
typedef uint8_t LZ4_byte;
typedef uint16_t LZ4_u16;
typedef uint32_t LZ4_u32;
#else
typedef signed char LZ4_i8;
typedef unsigned char LZ4_byte;
typedef unsigned short LZ4_u16;
typedef unsigned int LZ4_u32;
#endif
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
struct LZ4_stream_t_internal {
LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];
LZ4_u32 currentOffset;
LZ4_u32 tableType;
const LZ4_byte* dictionary;
const LZ4_stream_t_internal* dictCtx;
LZ4_u32 dictSize;
};
typedef struct {
const LZ4_byte* externalDict;
size_t extDictSize;
const LZ4_byte* prefixEnd;
size_t prefixSize;
} LZ4_streamDecode_t_internal;
/*! LZ4_stream_t :
* Do not use below internal definitions directly !
* Declare or allocate an LZ4_stream_t instead.
* LZ4_stream_t can also be created using LZ4_createStream(), which is recommended.
* The structure definition can be convenient for static allocation
* (on stack, or as part of larger structure).
* Init this structure with LZ4_initStream() before first use.
* note : only use this definition in association with static linking !
* this definition is not API/ABI safe, and may change in future versions.
*/
#define LZ4_STREAMSIZE 16416 /* static size, for inter-version compatibility */
#define LZ4_STREAMSIZE_VOIDP (LZ4_STREAMSIZE / sizeof(void*))
union LZ4_stream_u {
void* table[LZ4_STREAMSIZE_VOIDP];
LZ4_stream_t_internal internal_donotuse;
}; /* previously typedef'd to LZ4_stream_t */
/*! LZ4_initStream() : v1.9.0+
* An LZ4_stream_t structure must be initialized at least once.
* This is automatically done when invoking LZ4_createStream(),
* but it's not when the structure is simply declared on stack (for example).
*
* Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t.
* It can also initialize any arbitrary buffer of sufficient size,
* and will @return a pointer of proper type upon initialization.
*
* Note : initialization fails if size and alignment conditions are not respected.
* In which case, the function will @return NULL.
* Note2: An LZ4_stream_t structure guarantees correct alignment and size.
* Note3: Before v1.9.0, use LZ4_resetStream() instead
*/
LZ4LIB_API LZ4_stream_t* LZ4_initStream (void* buffer, size_t size);
/*! LZ4_streamDecode_t :
* information structure to track an LZ4 stream during decompression.
* init this structure using LZ4_setStreamDecode() before first use.
* note : only use in association with static linking !
* this definition is not API/ABI safe,
* and may change in a future version !
*/
#define LZ4_STREAMDECODESIZE_U64 (4 + ((sizeof(void*)==16) ? 2 : 0) /*AS-400*/ )
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
union LZ4_streamDecode_u {
unsigned long long table[LZ4_STREAMDECODESIZE_U64];
LZ4_streamDecode_t_internal internal_donotuse;
} ; /* previously typedef'd to LZ4_streamDecode_t */
/*-************************************
* Obsolete Functions
**************************************/
/*! Deprecation warnings
*
* Deprecated functions make the compiler generate a warning when invoked.
* This is meant to invite users to update their source code.
* Should deprecation warnings be a problem, it is generally possible to disable them,
* typically with -Wno-deprecated-declarations for gcc
* or _CRT_SECURE_NO_WARNINGS in Visual.
*
* Another method is to define LZ4_DISABLE_DEPRECATE_WARNINGS
* before including the header file.
*/
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
#else
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
# define LZ4_DEPRECATED(message) [[deprecated(message)]]
# elif defined(_MSC_VER)
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
# elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
# else
# pragma message("WARNING: LZ4_DEPRECATED needs custom implementation for this compiler")
# define LZ4_DEPRECATED(message) /* disabled */
# endif
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
/*! Obsolete compression functions (since v1.7.3) */
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* src, char* dest, int srcSize);
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
/*! Obsolete decompression functions (since v1.8.0) */
LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
/* Obsolete streaming functions (since v1.7.0)
* degraded functionality; do not use!
*
* In order to perform streaming compression, these functions depended on data
* that is no longer tracked in the state. They have been preserved as well as
* possible: using them will still produce a correct output. However, they don't
* actually retain any history between compression calls. The compression ratio
* achieved will therefore be no better than compressing each chunk
* independently.
*/
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer);
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void);
LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
/*! Obsolete streaming decoding functions (since v1.7.0) */
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) :
* These functions used to be faster than LZ4_decompress_safe(),
* but this is no longer the case. They are now slower.
* This is because LZ4_decompress_fast() doesn't know the input size,
* and therefore must progress more cautiously into the input buffer to not read beyond the end of block.
* On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability.
* As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated.
*
* The last remaining LZ4_decompress_fast() specificity is that
* it can decompress a block without knowing its compressed size.
* Such functionality can be achieved in a more secure manner
* by employing LZ4_decompress_safe_partial().
*
* Parameters:
* originalSize : is the uncompressed size to regenerate.
* `dst` must be already allocated, its size must be >= 'originalSize' bytes.
* @return : number of bytes read from source buffer (== compressed size).
* The function expects to finish at block's end exactly.
* If the source stream is detected malformed, the function stops decoding and returns a negative result.
* note : LZ4_decompress_fast*() requires originalSize. Thanks to this information, it never writes past the output buffer.
* However, since it doesn't know its 'src' size, it may read an unknown amount of input, past input buffer bounds.
* Also, since match offsets are not validated, match reads from 'src' may underflow too.
* These issues never happen if input (compressed) data is correct.
* But they may happen if input data is invalid (error or intentional tampering).
* As a consequence, use these functions in trusted environments with trusted data **only**.
*/
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe() instead")
LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_continue() instead")
LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
LZ4_DEPRECATED("This function is deprecated and unsafe. Consider using LZ4_decompress_safe_usingDict() instead")
LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);
/*! LZ4_resetStream() :
* An LZ4_stream_t structure must be initialized at least once.
* This is done with LZ4_initStream(), or LZ4_resetStream().
* Consider switching to LZ4_initStream(),
* invoking LZ4_resetStream() will trigger deprecation warnings in the future.
*/
LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
#endif /* LZ4_H_98237428734687 */
#if defined (__cplusplus)
}
#endif
+1899
View File
File diff suppressed because it is too large. Load diff
+623
View File
@@ -0,0 +1,623 @@
/*
LZ4 auto-framing library
Header File
Copyright (C) 2011-2020, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
/* LZ4F is a stand-alone API able to create and decode LZ4 frames
* conformant with specification v1.6.1 in doc/lz4_Frame_format.md .
* Generated frames are compatible with `lz4` CLI.
*
* LZ4F also offers streaming capabilities.
*
* lz4.h is not required when using lz4frame.h,
* except to extract common constant such as LZ4_VERSION_NUMBER.
* */
#ifndef LZ4F_H_09782039843
#define LZ4F_H_09782039843
#if defined (__cplusplus)
extern "C" {
#endif
/* --- Dependency --- */
#include <stddef.h> /* size_t */
/**
Introduction
lz4frame.h implements LZ4 frame specification (doc/lz4_Frame_format.md).
lz4frame.h provides frame compression functions that take care
of encoding standard metadata alongside LZ4-compressed blocks.
*/
/*-***************************************************************
* Compiler specifics
*****************************************************************/
/* LZ4_DLL_EXPORT :
* Enable exporting of functions when building a Windows DLL
* LZ4FLIB_VISIBILITY :
* Control library symbols visibility.
*/
#ifndef LZ4FLIB_VISIBILITY
# if defined(__GNUC__) && (__GNUC__ >= 4)
# define LZ4FLIB_VISIBILITY __attribute__ ((visibility ("default")))
# else
# define LZ4FLIB_VISIBILITY
# endif
#endif
#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
# define LZ4FLIB_API __declspec(dllexport) LZ4FLIB_VISIBILITY
#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
# define LZ4FLIB_API __declspec(dllimport) LZ4FLIB_VISIBILITY
#else
# define LZ4FLIB_API LZ4FLIB_VISIBILITY
#endif
#ifdef LZ4F_DISABLE_DEPRECATE_WARNINGS
# define LZ4F_DEPRECATE(x) x
#else
# if defined(_MSC_VER)
# define LZ4F_DEPRECATE(x) x /* __declspec(deprecated) x - only works with C++ */
# elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
# define LZ4F_DEPRECATE(x) x __attribute__((deprecated))
# else
# define LZ4F_DEPRECATE(x) x /* no deprecation warning for this compiler */
# endif
#endif
/*-************************************
* Error management
**************************************/
typedef size_t LZ4F_errorCode_t;
LZ4FLIB_API unsigned LZ4F_isError(LZ4F_errorCode_t code); /**< tells when a function result is an error code */
LZ4FLIB_API const char* LZ4F_getErrorName(LZ4F_errorCode_t code); /**< return error code string; for debugging */
/*-************************************
* Frame compression types
************************************* */
/* #define LZ4F_ENABLE_OBSOLETE_ENUMS // uncomment to enable obsolete enums */
#ifdef LZ4F_ENABLE_OBSOLETE_ENUMS
# define LZ4F_OBSOLETE_ENUM(x) , LZ4F_DEPRECATE(x) = LZ4F_##x
#else
# define LZ4F_OBSOLETE_ENUM(x)
#endif
/* The larger the block size, the (slightly) better the compression ratio,
* though there are diminishing returns.
* Larger blocks also increase memory usage on both compression and decompression sides.
*/
typedef enum {
LZ4F_default=0,
LZ4F_max64KB=4,
LZ4F_max256KB=5,
LZ4F_max1MB=6,
LZ4F_max4MB=7
LZ4F_OBSOLETE_ENUM(max64KB)
LZ4F_OBSOLETE_ENUM(max256KB)
LZ4F_OBSOLETE_ENUM(max1MB)
LZ4F_OBSOLETE_ENUM(max4MB)
} LZ4F_blockSizeID_t;
/* Linked blocks sharply reduce inefficiencies when using small blocks,
* they compress better.
* However, some LZ4 decoders are only compatible with independent blocks */
typedef enum {
LZ4F_blockLinked=0,
LZ4F_blockIndependent
LZ4F_OBSOLETE_ENUM(blockLinked)
LZ4F_OBSOLETE_ENUM(blockIndependent)
} LZ4F_blockMode_t;
typedef enum {
LZ4F_noContentChecksum=0,
LZ4F_contentChecksumEnabled
LZ4F_OBSOLETE_ENUM(noContentChecksum)
LZ4F_OBSOLETE_ENUM(contentChecksumEnabled)
} LZ4F_contentChecksum_t;
typedef enum {
LZ4F_noBlockChecksum=0,
LZ4F_blockChecksumEnabled
} LZ4F_blockChecksum_t;
typedef enum {
LZ4F_frame=0,
LZ4F_skippableFrame
LZ4F_OBSOLETE_ENUM(skippableFrame)
} LZ4F_frameType_t;
#ifdef LZ4F_ENABLE_OBSOLETE_ENUMS
typedef LZ4F_blockSizeID_t blockSizeID_t;
typedef LZ4F_blockMode_t blockMode_t;
typedef LZ4F_frameType_t frameType_t;
typedef LZ4F_contentChecksum_t contentChecksum_t;
#endif
/*! LZ4F_frameInfo_t :
* makes it possible to set or read frame parameters.
* Structure must be first init to 0, using memset() or LZ4F_INIT_FRAMEINFO,
* setting all parameters to default.
* It's then possible to update selectively some parameters */
typedef struct {
LZ4F_blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB; 0 == default */
LZ4F_blockMode_t blockMode; /* LZ4F_blockLinked, LZ4F_blockIndependent; 0 == default */
LZ4F_contentChecksum_t contentChecksumFlag; /* 1: frame terminated with 32-bit checksum of decompressed data; 0: disabled (default) */
LZ4F_frameType_t frameType; /* read-only field : LZ4F_frame or LZ4F_skippableFrame */
unsigned long long contentSize; /* Size of uncompressed content ; 0 == unknown */
unsigned dictID; /* Dictionary ID, sent by compressor to help decoder select correct dictionary; 0 == no dictID provided */
LZ4F_blockChecksum_t blockChecksumFlag; /* 1: each block followed by a checksum of block's compressed data; 0: disabled (default) */
} LZ4F_frameInfo_t;
#define LZ4F_INIT_FRAMEINFO { LZ4F_default, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame, 0ULL, 0U, LZ4F_noBlockChecksum } /* v1.8.3+ */
/*! LZ4F_preferences_t :
* makes it possible to supply advanced compression instructions to streaming interface.
* Structure must be first init to 0, using memset() or LZ4F_INIT_PREFERENCES,
* setting all parameters to default.
* All reserved fields must be set to zero. */
typedef struct {
LZ4F_frameInfo_t frameInfo;
int compressionLevel; /* 0: default (fast mode); values > LZ4HC_CLEVEL_MAX count as LZ4HC_CLEVEL_MAX; values < 0 trigger "fast acceleration" */
unsigned autoFlush; /* 1: always flush; reduces usage of internal buffers */
unsigned favorDecSpeed; /* 1: parser favors decompression speed vs compression ratio. Only works for high compression modes (>= LZ4HC_CLEVEL_OPT_MIN) */ /* v1.8.2+ */
unsigned reserved[3]; /* must be zero for forward compatibility */
} LZ4F_preferences_t;
#define LZ4F_INIT_PREFERENCES { LZ4F_INIT_FRAMEINFO, 0, 0u, 0u, { 0u, 0u, 0u } } /* v1.8.3+ */
/*-*********************************
* Simple compression function
***********************************/
LZ4FLIB_API int LZ4F_compressionLevel_max(void); /* v1.8.0+ */
/*! LZ4F_compressFrameBound() :
* Returns the maximum possible compressed size with LZ4F_compressFrame() given srcSize and preferences.
* `preferencesPtr` is optional. It can be replaced by NULL, in which case, the function will assume default preferences.
* Note : this result is only usable with LZ4F_compressFrame().
* It may also be used with LZ4F_compressUpdate() _if no flush() operation_ is performed.
*/
LZ4FLIB_API size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr);
/*! LZ4F_compressFrame() :
* Compress an entire srcBuffer into a valid LZ4 frame.
* dstCapacity MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr).
* The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.
* @return : number of bytes written into dstBuffer.
* or an error code if it fails (can be tested using LZ4F_isError())
*/
LZ4FLIB_API size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity,
const void* srcBuffer, size_t srcSize,
const LZ4F_preferences_t* preferencesPtr);
/*-***********************************
* Advanced compression functions
*************************************/
typedef struct LZ4F_cctx_s LZ4F_cctx; /* incomplete type */
typedef LZ4F_cctx* LZ4F_compressionContext_t; /* for compatibility with previous API version */
typedef struct {
unsigned stableSrc; /* 1 == src content will remain present on future calls to LZ4F_compress(); skip copying src content within tmp buffer */
unsigned reserved[3];
} LZ4F_compressOptions_t;
/*--- Resource Management ---*/
#define LZ4F_VERSION 100 /* This number can be used to check for an incompatible API breaking change */
LZ4FLIB_API unsigned LZ4F_getVersion(void);
/*! LZ4F_createCompressionContext() :
* The first thing to do is to create a compressionContext object, which will be used in all compression operations.
* This is achieved using LZ4F_createCompressionContext(), which takes as argument a version.
* The version provided MUST be LZ4F_VERSION. It is intended to track potential version mismatch, notably when using DLL.
* The function will provide a pointer to a fully allocated LZ4F_cctx object.
* If @return != zero, there was an error during context creation.
* Object can release its memory using LZ4F_freeCompressionContext();
*/
LZ4FLIB_API LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** cctxPtr, unsigned version);
LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctx);
/*---- Compression ----*/
#define LZ4F_HEADER_SIZE_MIN 7 /* LZ4 Frame header size can vary, depending on selected paramaters */
#define LZ4F_HEADER_SIZE_MAX 19
/* Size in bytes of a block header in little-endian format. Highest bit indicates if block data is uncompressed */
#define LZ4F_BLOCK_HEADER_SIZE 4
/* Size in bytes of a block checksum footer in little-endian format. */
#define LZ4F_BLOCK_CHECKSUM_SIZE 4
/* Size in bytes of the content checksum. */
#define LZ4F_CONTENT_CHECKSUM_SIZE 4
/*! LZ4F_compressBegin() :
* will write the frame header into dstBuffer.
* dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes.
* `prefsPtr` is optional : you can provide NULL as argument, all preferences will then be set to default.
* @return : number of bytes written into dstBuffer for the header
* or an error code (which can be tested using LZ4F_isError())
*/
LZ4FLIB_API size_t LZ4F_compressBegin(LZ4F_cctx* cctx,
void* dstBuffer, size_t dstCapacity,
const LZ4F_preferences_t* prefsPtr);
/*! LZ4F_compressBound() :
* Provides minimum dstCapacity required to guarantee success of
* LZ4F_compressUpdate(), given a srcSize and preferences, for a worst case scenario.
* When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() instead.
* Note that the result is only valid for a single invocation of LZ4F_compressUpdate().
* When invoking LZ4F_compressUpdate() multiple times,
* if the output buffer is gradually filled up instead of emptied and re-used from its start,
* one must check if there is enough remaining capacity before each invocation, using LZ4F_compressBound().
* @return is always the same for a srcSize and prefsPtr.
* prefsPtr is optional : when NULL is provided, preferences will be set to cover worst case scenario.
* tech details :
* @return if automatic flushing is not enabled, includes the possibility that internal buffer might already be filled by up to (blockSize-1) bytes.
* It also includes frame footer (ending + checksum), since it might be generated by LZ4F_compressEnd().
* @return doesn't include frame header, as it was already generated by LZ4F_compressBegin().
*/
LZ4FLIB_API size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* prefsPtr);
/*! LZ4F_compressUpdate() :
* LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.
* Important rule: dstCapacity MUST be large enough to ensure operation success even in worst case situations.
* This value is provided by LZ4F_compressBound().
* If this condition is not respected, LZ4F_compress() will fail (result is an errorCode).
* LZ4F_compressUpdate() doesn't guarantee error recovery.
* When an error occurs, compression context must be freed or resized.
* `cOptPtr` is optional : NULL can be provided, in which case all options are set to default.
* @return : number of bytes written into `dstBuffer` (it can be zero, meaning input data was just buffered).
* or an error code if it fails (which can be tested using LZ4F_isError())
*/
LZ4FLIB_API size_t LZ4F_compressUpdate(LZ4F_cctx* cctx,
void* dstBuffer, size_t dstCapacity,
const void* srcBuffer, size_t srcSize,
const LZ4F_compressOptions_t* cOptPtr);
/*! LZ4F_flush() :
* When data must be generated and sent immediately, without waiting for a block to be completely filled,
* it's possible to call LZ4_flush(). It will immediately compress any data buffered within cctx.
* `dstCapacity` must be large enough to ensure the operation will be successful.
* `cOptPtr` is optional : it's possible to provide NULL, all options will be set to default.
* @return : nb of bytes written into dstBuffer (can be zero, when there is no data stored within cctx)
* or an error code if it fails (which can be tested using LZ4F_isError())
* Note : LZ4F_flush() is guaranteed to be successful when dstCapacity >= LZ4F_compressBound(0, prefsPtr).
*/
LZ4FLIB_API size_t LZ4F_flush(LZ4F_cctx* cctx,
void* dstBuffer, size_t dstCapacity,
const LZ4F_compressOptions_t* cOptPtr);
/*! LZ4F_compressEnd() :
* To properly finish an LZ4 frame, invoke LZ4F_compressEnd().
* It will flush whatever data remained within `cctx` (like LZ4_flush())
* and properly finalize the frame, with an endMark and a checksum.
* `cOptPtr` is optional : NULL can be provided, in which case all options will be set to default.
* @return : nb of bytes written into dstBuffer, necessarily >= 4 (endMark),
* or an error code if it fails (which can be tested using LZ4F_isError())
* Note : LZ4F_compressEnd() is guaranteed to be successful when dstCapacity >= LZ4F_compressBound(0, prefsPtr).
* A successful call to LZ4F_compressEnd() makes `cctx` available again for another compression task.
*/
LZ4FLIB_API size_t LZ4F_compressEnd(LZ4F_cctx* cctx,
void* dstBuffer, size_t dstCapacity,
const LZ4F_compressOptions_t* cOptPtr);
/*-*********************************
* Decompression functions
***********************************/
typedef struct LZ4F_dctx_s LZ4F_dctx; /* incomplete type */
typedef LZ4F_dctx* LZ4F_decompressionContext_t; /* compatibility with previous API versions */
typedef struct {
unsigned stableDst; /* pledges that last 64KB decompressed data will remain available unmodified. This optimization skips storage operations in tmp buffers. */
unsigned reserved[3]; /* must be set to zero for forward compatibility */
} LZ4F_decompressOptions_t;
/* Resource management */
/*! LZ4F_createDecompressionContext() :
* Create an LZ4F_dctx object, to track all decompression operations.
* The version provided MUST be LZ4F_VERSION.
* The function provides a pointer to an allocated and initialized LZ4F_dctx object.
* The result is an errorCode, which can be tested using LZ4F_isError().
* dctx memory can be released using LZ4F_freeDecompressionContext();
* Result of LZ4F_freeDecompressionContext() indicates current state of decompressionContext when being released.
* That is, it should be == 0 if decompression has been completed fully and correctly.
*/
LZ4FLIB_API LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** dctxPtr, unsigned version);
LZ4FLIB_API LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx);
/*-***********************************
* Streaming decompression functions
*************************************/
#define LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH 5
/*! LZ4F_headerSize() : v1.9.0+
* Provide the header size of a frame starting at `src`.
* `srcSize` must be >= LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH,
* which is enough to decode the header length.
* @return : size of frame header
* or an error code, which can be tested using LZ4F_isError()
* note : Frame header size is variable, but is guaranteed to be
* >= LZ4F_HEADER_SIZE_MIN bytes, and <= LZ4F_HEADER_SIZE_MAX bytes.
*/
LZ4FLIB_API size_t LZ4F_headerSize(const void* src, size_t srcSize);
/*! LZ4F_getFrameInfo() :
* This function extracts frame parameters (max blockSize, dictID, etc.).
* Its usage is optional: user can call LZ4F_decompress() directly.
*
* Extracted information will fill an existing LZ4F_frameInfo_t structure.
* This can be useful for allocation and dictionary identification purposes.
*
* LZ4F_getFrameInfo() can work in the following situations :
*
* 1) At the beginning of a new frame, before any invocation of LZ4F_decompress().
* It will decode header from `srcBuffer`,
* consuming the header and starting the decoding process.
*
* Input size must be large enough to contain the full frame header.
* Frame header size can be known beforehand by LZ4F_headerSize().
* Frame header size is variable, but is guaranteed to be >= LZ4F_HEADER_SIZE_MIN bytes,
* and not more than <= LZ4F_HEADER_SIZE_MAX bytes.
* Hence, blindly providing LZ4F_HEADER_SIZE_MAX bytes or more will always work.
* It's allowed to provide more input data than the header size,
* LZ4F_getFrameInfo() will only consume the header.
*
* If input size is not large enough,
* aka if it's smaller than header size,
* function will fail and return an error code.
*
* 2) After decoding has been started,
* it's possible to invoke LZ4F_getFrameInfo() anytime
* to extract already decoded frame parameters stored within dctx.
*
* Note that, if decoding has barely started,
* and not yet read enough information to decode the header,
* LZ4F_getFrameInfo() will fail.
*
* The number of bytes consumed from srcBuffer will be updated in *srcSizePtr (necessarily <= original value).
* LZ4F_getFrameInfo() only consumes bytes when decoding has not yet started,
* and when decoding the header has been successful.
* Decompression must then resume from (srcBuffer + *srcSizePtr).
*
* @return : a hint about how many srcSize bytes LZ4F_decompress() expects for next call,
* or an error code which can be tested using LZ4F_isError().
* note 1 : in case of error, dctx is not modified. Decoding operation can resume from beginning safely.
* note 2 : frame parameters are *copied into* an already allocated LZ4F_frameInfo_t structure.
*/
LZ4FLIB_API size_t LZ4F_getFrameInfo(LZ4F_dctx* dctx,
LZ4F_frameInfo_t* frameInfoPtr,
const void* srcBuffer, size_t* srcSizePtr);
/*! LZ4F_decompress() :
* Call this function repetitively to regenerate data compressed in `srcBuffer`.
*
* The function requires a valid dctx state.
* It will read up to *srcSizePtr bytes from srcBuffer,
* and decompress data into dstBuffer, of capacity *dstSizePtr.
*
* The nb of bytes consumed from srcBuffer will be written into *srcSizePtr (necessarily <= original value).
* The nb of bytes decompressed into dstBuffer will be written into *dstSizePtr (necessarily <= original value).
*
* The function does not necessarily read all input bytes, so always check value in *srcSizePtr.
* Unconsumed source data must be presented again in subsequent invocations.
*
* `dstBuffer` can freely change between each consecutive function invocation.
* `dstBuffer` content will be overwritten.
*
* @return : an hint of how many `srcSize` bytes LZ4F_decompress() expects for next call.
* Schematically, it's the size of the current (or remaining) compressed block + header of next block.
* Respecting the hint provides some small speed benefit, because it skips intermediate buffers.
* This is just a hint though, it's always possible to provide any srcSize.
*
* When a frame is fully decoded, @return will be 0 (no more data expected).
* When provided with more bytes than necessary to decode a frame,
* LZ4F_decompress() will stop reading exactly at end of current frame, and @return 0.
*
* If decompression failed, @return is an error code, which can be tested using LZ4F_isError().
* After a decompression error, the `dctx` context is not resumable.
* Use LZ4F_resetDecompressionContext() to return to clean state.
*
* After a frame is fully decoded, dctx can be used again to decompress another frame.
*/
LZ4FLIB_API size_t LZ4F_decompress(LZ4F_dctx* dctx,
void* dstBuffer, size_t* dstSizePtr,
const void* srcBuffer, size_t* srcSizePtr,
const LZ4F_decompressOptions_t* dOptPtr);
/*! LZ4F_resetDecompressionContext() : added in v1.8.0
* In case of an error, the context is left in "undefined" state.
* In which case, it's necessary to reset it, before re-using it.
* This method can also be used to abruptly stop any unfinished decompression,
* and start a new one using same context resources. */
LZ4FLIB_API void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx); /* always successful */
#if defined (__cplusplus)
}
#endif
#endif /* LZ4F_H_09782039843 */
#if defined(LZ4F_STATIC_LINKING_ONLY) && !defined(LZ4F_H_STATIC_09782039843)
#define LZ4F_H_STATIC_09782039843
#if defined (__cplusplus)
extern "C" {
#endif
/* These declarations are not stable and may change in the future.
* They are therefore only safe to depend on
* when the caller is statically linked against the library.
* To access their declarations, define LZ4F_STATIC_LINKING_ONLY.
*
* By default, these symbols aren't published into shared/dynamic libraries.
* You can override this behavior and force them to be published
* by defining LZ4F_PUBLISH_STATIC_FUNCTIONS.
* Use at your own risk.
*/
#ifdef LZ4F_PUBLISH_STATIC_FUNCTIONS
# define LZ4FLIB_STATIC_API LZ4FLIB_API
#else
# define LZ4FLIB_STATIC_API
#endif
/* --- Error List --- */
#define LZ4F_LIST_ERRORS(ITEM) \
ITEM(OK_NoError) \
ITEM(ERROR_GENERIC) \
ITEM(ERROR_maxBlockSize_invalid) \
ITEM(ERROR_blockMode_invalid) \
ITEM(ERROR_contentChecksumFlag_invalid) \
ITEM(ERROR_compressionLevel_invalid) \
ITEM(ERROR_headerVersion_wrong) \
ITEM(ERROR_blockChecksum_invalid) \
ITEM(ERROR_reservedFlag_set) \
ITEM(ERROR_allocation_failed) \
ITEM(ERROR_srcSize_tooLarge) \
ITEM(ERROR_dstMaxSize_tooSmall) \
ITEM(ERROR_frameHeader_incomplete) \
ITEM(ERROR_frameType_unknown) \
ITEM(ERROR_frameSize_wrong) \
ITEM(ERROR_srcPtr_wrong) \
ITEM(ERROR_decompressionFailed) \
ITEM(ERROR_headerChecksum_invalid) \
ITEM(ERROR_contentChecksum_invalid) \
ITEM(ERROR_frameDecoding_alreadyStarted) \
ITEM(ERROR_maxCode)
#define LZ4F_GENERATE_ENUM(ENUM) LZ4F_##ENUM,
/* enum list is exposed, to handle specific errors */
typedef enum { LZ4F_LIST_ERRORS(LZ4F_GENERATE_ENUM)
_LZ4F_dummy_error_enum_for_c89_never_used } LZ4F_errorCodes;
LZ4FLIB_STATIC_API LZ4F_errorCodes LZ4F_getErrorCode(size_t functionResult);
LZ4FLIB_STATIC_API size_t LZ4F_getBlockSize(unsigned);
/**********************************
* Bulk processing dictionary API
*********************************/
/* A Dictionary is useful for the compression of small messages (KB range).
* It dramatically improves compression efficiency.
*
* LZ4 can ingest any input as dictionary, though only the last 64 KB are useful.
* Best results are generally achieved by using Zstandard's Dictionary Builder
* to generate a high-quality dictionary from a set of samples.
*
* Loading a dictionary has a cost, since it involves construction of tables.
* The Bulk processing dictionary API makes it possible to share this cost
* over an arbitrary number of compression jobs, even concurrently,
* markedly improving compression latency for these cases.
*
* The same dictionary will have to be used on the decompression side
* for decoding to be successful.
* To help identify the correct dictionary at decoding stage,
* the frame header allows optional embedding of a dictID field.
*/
typedef struct LZ4F_CDict_s LZ4F_CDict;
/*! LZ4_createCDict() :
* When compressing multiple messages / blocks using the same dictionary, it's recommended to load it just once.
* LZ4_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.
* LZ4_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
* `dictBuffer` can be released after LZ4_CDict creation, since its content is copied within CDict */
LZ4FLIB_STATIC_API LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize);
LZ4FLIB_STATIC_API void LZ4F_freeCDict(LZ4F_CDict* CDict);
/*! LZ4_compressFrame_usingCDict() :
* Compress an entire srcBuffer into a valid LZ4 frame using a digested Dictionary.
* cctx must point to a context created by LZ4F_createCompressionContext().
* If cdict==NULL, compress without a dictionary.
* dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr).
* If this condition is not respected, function will fail (@return an errorCode).
* The LZ4F_preferences_t structure is optional : you may provide NULL as argument,
* but it's not recommended, as it's the only way to provide dictID in the frame header.
* @return : number of bytes written into dstBuffer.
* or an error code if it fails (can be tested using LZ4F_isError()) */
LZ4FLIB_STATIC_API size_t LZ4F_compressFrame_usingCDict(
LZ4F_cctx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const LZ4F_CDict* cdict,
const LZ4F_preferences_t* preferencesPtr);
/*! LZ4F_compressBegin_usingCDict() :
* Inits streaming dictionary compression, and writes the frame header into dstBuffer.
* dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes.
* `prefsPtr` is optional : you may provide NULL as argument,
* however, it's the only way to provide dictID in the frame header.
* @return : number of bytes written into dstBuffer for the header,
* or an error code (which can be tested using LZ4F_isError()) */
LZ4FLIB_STATIC_API size_t LZ4F_compressBegin_usingCDict(
LZ4F_cctx* cctx,
void* dstBuffer, size_t dstCapacity,
const LZ4F_CDict* cdict,
const LZ4F_preferences_t* prefsPtr);
/*! LZ4F_decompress_usingDict() :
* Same as LZ4F_decompress(), using a predefined dictionary.
* Dictionary is used "in place", without any preprocessing.
* It must remain accessible throughout the entire frame decoding. */
LZ4FLIB_STATIC_API size_t LZ4F_decompress_usingDict(
LZ4F_dctx* dctxPtr,
void* dstBuffer, size_t* dstSizePtr,
const void* srcBuffer, size_t* srcSizePtr,
const void* dict, size_t dictSize,
const LZ4F_decompressOptions_t* decompressOptionsPtr);
#if defined (__cplusplus)
}
#endif
#endif /* defined(LZ4F_STATIC_LINKING_ONLY) && !defined(LZ4F_H_STATIC_09782039843) */
+47
View File
@@ -0,0 +1,47 @@
/*
LZ4 auto-framing library
Header File for static linking only
Copyright (C) 2011-2020, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#ifndef LZ4FRAME_STATIC_H_0398209384
#define LZ4FRAME_STATIC_H_0398209384
/* The declarations that formerly were made here have been merged into
* lz4frame.h, protected by the LZ4F_STATIC_LINKING_ONLY macro. Going forward,
* it is recommended to simply include that header directly.
*/
#define LZ4F_STATIC_LINKING_ONLY
#include "lz4frame.h"
#endif /* LZ4FRAME_STATIC_H_0398209384 */
+1619
View File
File diff suppressed because it is too large. Load diff
+413
View File
@@ -0,0 +1,413 @@
/*
LZ4 HC - High Compression Mode of LZ4
Header File
Copyright (C) 2011-2020, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 source repository : https://github.com/lz4/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
#ifndef LZ4_HC_H_19834876238432
#define LZ4_HC_H_19834876238432
#if defined (__cplusplus)
extern "C" {
#endif
/* --- Dependency --- */
/* note : lz4hc requires lz4.h/lz4.c for compilation */
#include "lz4.h" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */
/* --- Useful constants --- */
#define LZ4HC_CLEVEL_MIN 3
#define LZ4HC_CLEVEL_DEFAULT 9
#define LZ4HC_CLEVEL_OPT_MIN 10
#define LZ4HC_CLEVEL_MAX 12
/*-************************************
* Block Compression
**************************************/
/*! LZ4_compress_HC() :
* Compress data from `src` into `dst`, using the powerful but slower "HC" algorithm.
* `dst` must be already allocated.
* Compression is guaranteed to succeed if `dstCapacity >= LZ4_compressBound(srcSize)` (see "lz4.h")
* Max supported `srcSize` value is LZ4_MAX_INPUT_SIZE (see "lz4.h")
* `compressionLevel` : any value between 1 and LZ4HC_CLEVEL_MAX will work.
* Values > LZ4HC_CLEVEL_MAX behave the same as LZ4HC_CLEVEL_MAX.
* @return : the number of bytes written into 'dst'
* or 0 if compression fails.
*/
LZ4LIB_API int LZ4_compress_HC (const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel);
/* Note :
* Decompression functions are provided within "lz4.h" (BSD license)
*/
/*! LZ4_compress_HC_extStateHC() :
* Same as LZ4_compress_HC(), but using an externally allocated memory segment for `state`.
* `state` size is provided by LZ4_sizeofStateHC().
* Memory segment must be aligned on 8-bytes boundaries (which a normal malloc() should do properly).
*/
LZ4LIB_API int LZ4_sizeofStateHC(void);
LZ4LIB_API int LZ4_compress_HC_extStateHC(void* stateHC, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
/*! LZ4_compress_HC_destSize() : v1.9.0+
* Will compress as much data as possible from `src`
* to fit into `targetDstSize` budget.
* Result is provided in 2 parts :
* @return : the number of bytes written into 'dst' (necessarily <= targetDstSize)
* or 0 if compression fails.
* `srcSizePtr` : on success, *srcSizePtr is updated to indicate how much bytes were read from `src`
*/
LZ4LIB_API int LZ4_compress_HC_destSize(void* stateHC,
const char* src, char* dst,
int* srcSizePtr, int targetDstSize,
int compressionLevel);
/*-************************************
* Streaming Compression
* Bufferless synchronous API
**************************************/
typedef union LZ4_streamHC_u LZ4_streamHC_t; /* incomplete type (defined later) */
/*! LZ4_createStreamHC() and LZ4_freeStreamHC() :
* These functions create and release memory for LZ4 HC streaming state.
* Newly created states are automatically initialized.
* A same state can be used multiple times consecutively,
* starting with LZ4_resetStreamHC_fast() to start a new stream of blocks.
*/
LZ4LIB_API LZ4_streamHC_t* LZ4_createStreamHC(void);
LZ4LIB_API int LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr);
/*
These functions compress data in successive blocks of any size,
using previous blocks as dictionary, to improve compression ratio.
One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.
There is an exception for ring buffers, which can be smaller than 64 KB.
Ring-buffer scenario is automatically detected and handled within LZ4_compress_HC_continue().
Before starting compression, state must be allocated and properly initialized.
LZ4_createStreamHC() does both, though compression level is set to LZ4HC_CLEVEL_DEFAULT.
Selecting the compression level can be done with LZ4_resetStreamHC_fast() (starts a new stream)
or LZ4_setCompressionLevel() (anytime, between blocks in the same stream) (experimental).
LZ4_resetStreamHC_fast() only works on states which have been properly initialized at least once,
which is automatically the case when state is created using LZ4_createStreamHC().
After reset, a first "fictional block" can be designated as initial dictionary,
using LZ4_loadDictHC() (Optional).
Invoke LZ4_compress_HC_continue() to compress each successive block.
The number of blocks is unlimited.
Previous input blocks, including initial dictionary when present,
must remain accessible and unmodified during compression.
It's allowed to update compression level anytime between blocks,
using LZ4_setCompressionLevel() (experimental).
'dst' buffer should be sized to handle worst case scenarios
(see LZ4_compressBound(), it ensures compression success).
In case of failure, the API does not guarantee recovery,
so the state _must_ be reset.
To ensure compression success
whenever `dst` buffer size cannot be made >= LZ4_compressBound(),
consider using LZ4_compress_HC_continue_destSize().
Whenever previous input blocks can't be preserved unmodified in-place during compression of next blocks,
it's possible to copy the last blocks into a more stable memory space, using LZ4_saveDictHC().
Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer' (<= 64 KB)
After completing a streaming compression,
it's possible to start a new stream of blocks, using the same LZ4_streamHC_t state,
just by resetting it, using LZ4_resetStreamHC_fast().
*/
LZ4LIB_API void LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, int compressionLevel); /* v1.9.0+ */
LZ4LIB_API int LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize);
LZ4LIB_API int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr,
const char* src, char* dst,
int srcSize, int maxDstSize);
/*! LZ4_compress_HC_continue_destSize() : v1.9.0+
* Similar to LZ4_compress_HC_continue(),
* but will read as much data as possible from `src`
* to fit into `targetDstSize` budget.
* Result is provided into 2 parts :
* @return : the number of bytes written into 'dst' (necessarily <= targetDstSize)
* or 0 if compression fails.
* `srcSizePtr` : on success, *srcSizePtr will be updated to indicate how much bytes were read from `src`.
* Note that this function may not consume the entire input.
*/
LZ4LIB_API int LZ4_compress_HC_continue_destSize(LZ4_streamHC_t* LZ4_streamHCPtr,
const char* src, char* dst,
int* srcSizePtr, int targetDstSize);
LZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);
/*^**********************************************
* !!!!!! STATIC LINKING ONLY !!!!!!
***********************************************/
/*-******************************************************************
* PRIVATE DEFINITIONS :
* Do not use these definitions directly.
* They are merely exposed to allow static allocation of `LZ4_streamHC_t`.
* Declare an `LZ4_streamHC_t` directly, rather than any type below.
* Even then, only do so in the context of static linking, as definitions may change between versions.
********************************************************************/
#define LZ4HC_DICTIONARY_LOGSIZE 16
#define LZ4HC_MAXD (1<<LZ4HC_DICTIONARY_LOGSIZE)
#define LZ4HC_MAXD_MASK (LZ4HC_MAXD - 1)
#define LZ4HC_HASH_LOG 15
#define LZ4HC_HASHTABLESIZE (1 << LZ4HC_HASH_LOG)
#define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1)
typedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal;
struct LZ4HC_CCtx_internal
{
LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE];
LZ4_u16 chainTable[LZ4HC_MAXD];
const LZ4_byte* end; /* next block here to continue on current prefix */
const LZ4_byte* base; /* All index relative to this position */
const LZ4_byte* dictBase; /* alternate base for extDict */
LZ4_u32 dictLimit; /* below that point, need extDict */
LZ4_u32 lowLimit; /* below that point, no more dict */
LZ4_u32 nextToUpdate; /* index from which to continue dictionary update */
short compressionLevel;
LZ4_i8 favorDecSpeed; /* favor decompression speed if this flag set,
otherwise, favor compression ratio */
LZ4_i8 dirty; /* stream has to be fully reset if this flag is set */
const LZ4HC_CCtx_internal* dictCtx;
};
/* Do not use these definitions directly !
* Declare or allocate an LZ4_streamHC_t instead.
*/
#define LZ4_STREAMHCSIZE 262200 /* static size, for inter-version compatibility */
#define LZ4_STREAMHCSIZE_VOIDP (LZ4_STREAMHCSIZE / sizeof(void*))
union LZ4_streamHC_u {
void* table[LZ4_STREAMHCSIZE_VOIDP];
LZ4HC_CCtx_internal internal_donotuse;
}; /* previously typedef'd to LZ4_streamHC_t */
/* LZ4_streamHC_t :
* This structure allows static allocation of LZ4 HC streaming state.
* This can be used to allocate statically, on state, or as part of a larger structure.
*
* Such state **must** be initialized using LZ4_initStreamHC() before first use.
*
* Note that invoking LZ4_initStreamHC() is not required when
* the state was created using LZ4_createStreamHC() (which is recommended).
* Using the normal builder, a newly created state is automatically initialized.
*
* Static allocation shall only be used in combination with static linking.
*/
/* LZ4_initStreamHC() : v1.9.0+
* Required before first use of a statically allocated LZ4_streamHC_t.
* Before v1.9.0 : use LZ4_resetStreamHC() instead
*/
LZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size);
/*-************************************
* Deprecated Functions
**************************************/
/* see lz4.h LZ4_DISABLE_DEPRECATE_WARNINGS to turn off deprecation warnings */
/* deprecated compression functions */
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC (const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC_extStateHC() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize);
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
/* Obsolete streaming functions; degraded functionality; do not use!
*
* In order to perform streaming compression, these functions depended on data
* that is no longer tracked in the state. They have been preserved as well as
* possible: using them will still produce a correct output. However, use of
* LZ4_slideInputBufferHC() will truncate the history of the stream, rather
* than preserve a window-sized chunk of history.
*/
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer);
LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data);
LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC (void* LZ4HC_Data);
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void);
LZ4_DEPRECATED("use LZ4_initStreamHC() instead") LZ4LIB_API int LZ4_resetStreamStateHC(void* state, char* inputBuffer);
/* LZ4_resetStreamHC() is now replaced by LZ4_initStreamHC().
* The intention is to emphasize the difference with LZ4_resetStreamHC_fast(),
* which is now the recommended function to start a new stream of blocks,
* but cannot be used to initialize a memory segment containing arbitrary garbage data.
*
* It is recommended to switch to LZ4_initStreamHC().
* LZ4_resetStreamHC() will generate deprecation warnings in a future version.
*/
LZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel);
#if defined (__cplusplus)
}
#endif
#endif /* LZ4_HC_H_19834876238432 */
/*-**************************************************
* !!!!! STATIC LINKING ONLY !!!!!
* Following definitions are considered experimental.
* They should not be linked from DLL,
* as there is no guarantee of API stability yet.
* Prototypes will be promoted to "stable" status
* after successfull usage in real-life scenarios.
***************************************************/
#ifdef LZ4_HC_STATIC_LINKING_ONLY /* protection macro */
#ifndef LZ4_HC_SLO_098092834
#define LZ4_HC_SLO_098092834
#define LZ4_STATIC_LINKING_ONLY /* LZ4LIB_STATIC_API */
#include "lz4.h"
#if defined (__cplusplus)
extern "C" {
#endif
/*! LZ4_setCompressionLevel() : v1.8.0+ (experimental)
* It's possible to change compression level
* between successive invocations of LZ4_compress_HC_continue*()
* for dynamic adaptation.
*/
LZ4LIB_STATIC_API void LZ4_setCompressionLevel(
LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel);
/*! LZ4_favorDecompressionSpeed() : v1.8.2+ (experimental)
* Opt. Parser will favor decompression speed over compression ratio.
* Only applicable to levels >= LZ4HC_CLEVEL_OPT_MIN.
*/
LZ4LIB_STATIC_API void LZ4_favorDecompressionSpeed(
LZ4_streamHC_t* LZ4_streamHCPtr, int favor);
/*! LZ4_resetStreamHC_fast() : v1.9.0+
* When an LZ4_streamHC_t is known to be in a internally coherent state,
* it can often be prepared for a new compression with almost no work, only
* sometimes falling back to the full, expensive reset that is always required
* when the stream is in an indeterminate state (i.e., the reset performed by
* LZ4_resetStreamHC()).
*
* LZ4_streamHCs are guaranteed to be in a valid state when:
* - returned from LZ4_createStreamHC()
* - reset by LZ4_resetStreamHC()
* - memset(stream, 0, sizeof(LZ4_streamHC_t))
* - the stream was in a valid state and was reset by LZ4_resetStreamHC_fast()
* - the stream was in a valid state and was then used in any compression call
* that returned success
* - the stream was in an indeterminate state and was used in a compression
* call that fully reset the state (LZ4_compress_HC_extStateHC()) and that
* returned success
*
* Note:
* A stream that was last used in a compression call that returned an error
* may be passed to this function. However, it will be fully reset, which will
* clear any existing history and settings from the context.
*/
LZ4LIB_STATIC_API void LZ4_resetStreamHC_fast(
LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel);
/*! LZ4_compress_HC_extStateHC_fastReset() :
* A variant of LZ4_compress_HC_extStateHC().
*
* Using this variant avoids an expensive initialization step. It is only safe
* to call if the state buffer is known to be correctly initialized already
* (see above comment on LZ4_resetStreamHC_fast() for a definition of
* "correctly initialized"). From a high level, the difference is that this
* function initializes the provided state with a call to
* LZ4_resetStreamHC_fast() while LZ4_compress_HC_extStateHC() starts with a
* call to LZ4_resetStreamHC().
*/
LZ4LIB_STATIC_API int LZ4_compress_HC_extStateHC_fastReset (
void* state,
const char* src, char* dst,
int srcSize, int dstCapacity,
int compressionLevel);
/*! LZ4_attach_HC_dictionary() :
* This is an experimental API that allows for the efficient use of a
* static dictionary many times.
*
* Rather than re-loading the dictionary buffer into a working context before
* each compression, or copying a pre-loaded dictionary's LZ4_streamHC_t into a
* working LZ4_streamHC_t, this function introduces a no-copy setup mechanism,
* in which the working stream references the dictionary stream in-place.
*
* Several assumptions are made about the state of the dictionary stream.
* Currently, only streams which have been prepared by LZ4_loadDictHC() should
* be expected to work.
*
* Alternatively, the provided dictionary stream pointer may be NULL, in which
* case any existing dictionary stream is unset.
*
* A dictionary should only be attached to a stream without any history (i.e.,
* a stream that has just been reset).
*
* The dictionary will remain attached to the working stream only for the
* current stream session. Calls to LZ4_resetStreamHC(_fast) will remove the
* dictionary context association from the working stream. The dictionary
* stream (and source buffer) must remain in-place / accessible / unchanged
* through the lifetime of the stream session.
*/
LZ4LIB_STATIC_API void LZ4_attach_HC_dictionary(
LZ4_streamHC_t *working_stream,
const LZ4_streamHC_t *dictionary_stream);
#if defined (__cplusplus)
}
#endif
#endif /* LZ4_HC_SLO_098092834 */
#endif /* LZ4_HC_STATIC_LINKING_ONLY */
+1030
View File
File diff suppressed because it is too large. Load diff
+328
View File
@@ -0,0 +1,328 @@
/*
xxHash - Extremely Fast Hash algorithm
Header File
Copyright (C) 2012-2016, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- xxHash source repository : https://github.com/Cyan4973/xxHash
*/
/* Notice extracted from xxHash homepage :
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
It also successfully passes all tests from the SMHasher suite.
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
Name Speed Q.Score Author
xxHash 5.4 GB/s 10
CrapWow 3.2 GB/s 2 Andrew
MumurHash 3a 2.7 GB/s 10 Austin Appleby
SpookyHash 2.0 GB/s 10 Bob Jenkins
SBox 1.4 GB/s 9 Bret Mulvey
Lookup3 1.2 GB/s 9 Bob Jenkins
SuperFastHash 1.2 GB/s 1 Paul Hsieh
CityHash64 1.05 GB/s 10 Pike & Alakuijala
FNV 0.55 GB/s 5 Fowler, Noll, Vo
CRC32 0.43 GB/s 9
MD5-32 0.33 GB/s 10 Ronald L. Rivest
SHA1-32 0.28 GB/s 10
Q.Score is a measure of quality of the hash function.
It depends on successfully passing SMHasher test set.
10 is a perfect score.
A 64-bit version, named XXH64, is available since r35.
It offers much better speed, but for 64-bit applications only.
Name Speed on 64 bits Speed on 32 bits
XXH64 13.8 GB/s 1.9 GB/s
XXH32 6.8 GB/s 6.0 GB/s
*/
#ifndef XXHASH_H_5627135585666179
#define XXHASH_H_5627135585666179 1
#if defined (__cplusplus)
extern "C" {
#endif
/* ****************************
* Definitions
******************************/
#include <stddef.h> /* size_t */
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
/* ****************************
* API modifier
******************************/
/** XXH_INLINE_ALL (and XXH_PRIVATE_API)
* This is useful to include xxhash functions in `static` mode
* in order to inline them, and remove their symbol from the public list.
* Inlining can offer dramatic performance improvement on small keys.
* Methodology :
* #define XXH_INLINE_ALL
* #include "xxhash.h"
* `xxhash.c` is automatically included.
* It's not useful to compile and link it as a separate module.
*/
#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)
# ifndef XXH_STATIC_LINKING_ONLY
# define XXH_STATIC_LINKING_ONLY
# endif
# if defined(__GNUC__)
# define XXH_PUBLIC_API static __inline __attribute__((unused))
# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
# define XXH_PUBLIC_API static inline
# elif defined(_MSC_VER)
# define XXH_PUBLIC_API static __inline
# else
/* this version may generate warnings for unused static functions */
# define XXH_PUBLIC_API static
# endif
#else
# define XXH_PUBLIC_API /* do nothing */
#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */
/*! XXH_NAMESPACE, aka Namespace Emulation :
*
* If you want to include _and expose_ xxHash functions from within your own library,
* but also want to avoid symbol collisions with other libraries which may also include xxHash,
*
* you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library
* with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values).
*
* Note that no change is required within the calling program as long as it includes `xxhash.h` :
* regular symbol name will be automatically translated by this header.
*/
#ifdef XXH_NAMESPACE
# define XXH_CAT(A,B) A##B
# define XXH_NAME2(A,B) XXH_CAT(A,B)
# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber)
# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)
# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)
# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)
# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)
# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)
# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState)
# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash)
# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical)
# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)
# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)
# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)
# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)
# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)
# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)
# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState)
# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash)
# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical)
#endif
/* *************************************
* Version
***************************************/
#define XXH_VERSION_MAJOR 0
#define XXH_VERSION_MINOR 6
#define XXH_VERSION_RELEASE 5
#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
XXH_PUBLIC_API unsigned XXH_versionNumber (void);
/*-**********************************************************************
* 32-bit hash
************************************************************************/
typedef unsigned int XXH32_hash_t;
/*! XXH32() :
Calculate the 32-bit hash of sequence "length" bytes stored at memory address "input".
The memory between input & input+length must be valid (allocated and read-accessible).
"seed" can be used to alter the result predictably.
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */
XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed);
/*====== Streaming ======*/
typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */
XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void);
XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state);
XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed);
XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);
/*
* Streaming functions generate the xxHash of an input provided in multiple segments.
* Note that, for small input, they are slower than single-call functions, due to state management.
* For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized.
*
* XXH state must first be allocated, using XXH*_createState() .
*
* Start a new hash by initializing state with a seed, using XXH*_reset().
*
* Then, feed the hash state by calling XXH*_update() as many times as necessary.
* The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
*
* Finally, a hash value can be produced anytime, by using XXH*_digest().
* This function returns the nn-bits hash as an int or long long.
*
* It's still possible to continue inserting input into the hash state after a digest,
* and generate some new hashes later on, by calling again XXH*_digest().
*
* When done, free XXH state space if it was allocated dynamically.
*/
/*====== Canonical representation ======*/
typedef struct { unsigned char digest[4]; } XXH32_canonical_t;
XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash);
XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);
/* Default result type for XXH functions are primitive unsigned 32 and 64 bits.
* The canonical representation uses human-readable write convention, aka big-endian (large digits first).
* These functions allow transformation of hash result into and from its canonical format.
* This way, hash values can be written into a file / memory, and remain comparable on different systems and programs.
*/
#ifndef XXH_NO_LONG_LONG
/*-**********************************************************************
* 64-bit hash
************************************************************************/
typedef unsigned long long XXH64_hash_t;
/*! XXH64() :
Calculate the 64-bit hash of sequence of length "len" stored at memory address "input".
"seed" can be used to alter the result predictably.
This function runs faster on 64-bit systems, but slower on 32-bit systems (see benchmark).
*/
XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed);
/*====== Streaming ======*/
typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */
XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void);
XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state);
XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr);
/*====== Canonical representation ======*/
typedef struct { unsigned char digest[8]; } XXH64_canonical_t;
XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash);
XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src);
#endif /* XXH_NO_LONG_LONG */
#ifdef XXH_STATIC_LINKING_ONLY
/* ================================================================================================
This section contains declarations which are not guaranteed to remain stable.
They may change in future versions, becoming incompatible with a different version of the library.
These declarations should only be used with static linking.
Never use them in association with dynamic linking !
=================================================================================================== */
/* These definitions are only present to allow
* static allocation of XXH state, on stack or in a struct for example.
* Never **ever** use members directly. */
#if !defined (__VMS) \
&& (defined (__cplusplus) \
|| (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
# include <stdint.h>
struct XXH32_state_s {
uint32_t total_len_32;
uint32_t large_len;
uint32_t v1;
uint32_t v2;
uint32_t v3;
uint32_t v4;
uint32_t mem32[4];
uint32_t memsize;
uint32_t reserved; /* never read nor write, might be removed in a future version */
}; /* typedef'd to XXH32_state_t */
struct XXH64_state_s {
uint64_t total_len;
uint64_t v1;
uint64_t v2;
uint64_t v3;
uint64_t v4;
uint64_t mem64[4];
uint32_t memsize;
uint32_t reserved[2]; /* never read nor write, might be removed in a future version */
}; /* typedef'd to XXH64_state_t */
# else
struct XXH32_state_s {
unsigned total_len_32;
unsigned large_len;
unsigned v1;
unsigned v2;
unsigned v3;
unsigned v4;
unsigned mem32[4];
unsigned memsize;
unsigned reserved; /* never read nor write, might be removed in a future version */
}; /* typedef'd to XXH32_state_t */
# ifndef XXH_NO_LONG_LONG /* remove 64-bit support */
struct XXH64_state_s {
unsigned long long total_len;
unsigned long long v1;
unsigned long long v2;
unsigned long long v3;
unsigned long long v4;
unsigned long long mem64[4];
unsigned memsize;
unsigned reserved[2]; /* never read nor write, might be removed in a future version */
}; /* typedef'd to XXH64_state_t */
# endif
# endif
#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)
# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */
#endif
#endif /* XXH_STATIC_LINKING_ONLY */
#if defined (__cplusplus)
}
#endif
#endif /* XXHASH_H_5627135585666179 */
-4
View File
@@ -1134,10 +1134,6 @@ int CFred_mission_save::save_cmd_brief()
required_string_fred("#Command Briefing");
parse_comments(2);
if (The_mission.game_type & MISSION_TYPE_MULTI) {
return err;
} // no command briefings allowed in multiplayer missions.
save_custom_bitmap("$Background 640:",
"$Background 1024:",
Cur_cmd_brief->background[GR_640],
@@ -79,6 +79,7 @@ MissionSpecDialog::MissionSpecDialog(FredView* parent, EditorViewport* viewport)
connect(ui->toggleAutopilotCinematics, &QCheckBox::toggled, this, [this](bool param) {flagToggled(param, Mission::Mission_Flags::Use_ap_cinematics); });
connect(ui->toggleHardcodedAutopilot, &QCheckBox::toggled, this, [this](bool param) {flagToggled(param, Mission::Mission_Flags::Deactivate_ap); });
connect(ui->toggleAIControlStart, &QCheckBox::toggled, this, [this](bool param) {flagToggled(param, Mission::Mission_Flags::Player_start_ai); });
connect(ui->toggleChaseViewStart, &QCheckBox::toggled, this, [this](bool param) {flagToggled(param, Mission::Mission_Flags::Player_start_chase_view); });
connect(ui->toggle2DMission, &QCheckBox::toggled, this, [this](bool param) {flagToggled(param, Mission::Mission_Flags::Mission_2d); });
connect(ui->toggleGoalsInBriefing, &QCheckBox::toggled, this, [this](bool param) {flagToggled(param, Mission::Mission_Flags::Always_show_goals); });
connect(ui->toggleMissionEndToMainhall, &QCheckBox::toggled, this, [this](bool param) {flagToggled(param, Mission::Mission_Flags::End_to_mainhall); });
@@ -236,6 +237,7 @@ void MissionSpecDialog::updateFlags() {
auto flags = _model->getMissionFlags();
ui->toggle2DMission->setChecked(flags[Mission::Mission_Flags::Mission_2d]);
ui->toggleAIControlStart->setChecked(flags[Mission::Mission_Flags::Player_start_ai]);
ui->toggleChaseViewStart->setChecked(flags[Mission::Mission_Flags::Player_start_chase_view]);
ui->toggleAllTeamsAtWar->setChecked(flags[Mission::Mission_Flags::All_attack]);
ui->toggleAutopilotCinematics->setChecked(flags[Mission::Mission_Flags::Use_ap_cinematics]);
ui->toggleBeamFreeDefault->setChecked(flags[Mission::Mission_Flags::Beam_free_all_by_default]);
+10
View File
@@ -887,6 +887,16 @@
</attribute>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggleChaseViewStart">
<property name="text">
<string>Player Starts in Chase View</string>
</property>
<attribute name="buttonGroup">
<string notr="true">m_flagGroup</string>
</attribute>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggle2DMission">
<property name="text">
+5
View File
@@ -0,0 +1,5 @@
set(FSO_VERSION_MAJOR 21)
set(FSO_VERSION_MINOR 2)
set(FSO_VERSION_BUILD 0)
set(FSO_VERSION_REVISION 0)
set(FSO_VERSION_REVISION_STR )