Compare commits

..

9 Commits

302 changed files with 9405 additions and 16890 deletions

View File

@@ -1,7 +1,32 @@
task:
# Seems packages for it were removed from the mirrors
# name: freebsd-12-amd64
# freebsd_instance:
# image_family: freebsd-12-4
# setup_script:
# - pkg update
# - pkg install -y pkgconf git sdl2 python fontconfig opus
# - git submodule update --init --recursive
# test_script:
# - ./scripts/cirrus/build_freebsd.sh dedicated
# - ./scripts/cirrus/build_freebsd.sh full
task:
name: freebsd-13-amd64
freebsd_instance:
image_family: freebsd-13-2
setup_script:
- pkg update
- pkg install -y pkgconf git sdl2 python fontconfig opus
- git submodule update --init --recursive
test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated
- ./scripts/cirrus/build_freebsd.sh full
task:
name: freebsd-14-amd64
freebsd_instance:
image_family: freebsd-14-0
image_family: freebsd-14-0-snap
setup_script:
- pkg update
- pkg install -y pkgconf git sdl2 python fontconfig opus

View File

@@ -1,365 +1,9 @@
# this file is just a suggestion, you might follow it, you might not
# EditorConfig is awesome: https://EditorConfig.org
root = true
[*]
charset = utf-8
charset = latin1
end_of_line = lf
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
# Visual C++ Formatting settings
cpp_indent_braces = false
cpp_indent_multi_line_relative_to = innermost_parenthesis
cpp_indent_within_parentheses = indent
cpp_indent_preserve_within_parentheses = true
cpp_indent_case_contents = true
cpp_indent_case_labels = false
cpp_indent_case_contents_when_block = false
cpp_indent_lambda_braces_when_parameter = true
cpp_indent_goto_labels = one_left
cpp_indent_preprocessor = leftmost_column
cpp_indent_access_specifiers = false
cpp_indent_namespace_contents = true
cpp_indent_preserve_comments = false
cpp_new_line_before_open_brace_namespace = new_line
cpp_new_line_before_open_brace_type = new_line
cpp_new_line_before_open_brace_function = new_line
cpp_new_line_before_open_brace_block = new_line
cpp_new_line_before_open_brace_lambda = new_line
cpp_new_line_scope_braces_on_separate_lines = true
cpp_new_line_close_brace_same_line_empty_type = false
cpp_new_line_close_brace_same_line_empty_function = false
cpp_new_line_before_catch = true
cpp_new_line_before_else = true
cpp_new_line_before_while_in_do_while = false
cpp_space_before_function_open_parenthesis = remove
cpp_space_within_parameter_list_parentheses = true
cpp_space_between_empty_parameter_list_parentheses = true
cpp_space_after_keywords_in_control_flow_statements = false
cpp_space_within_control_flow_statement_parentheses = true
cpp_space_before_lambda_open_parenthesis = false
cpp_space_within_cast_parentheses = false
cpp_space_after_cast_close_parenthesis = false
cpp_space_within_expression_parentheses = true
cpp_space_before_block_open_brace = true
cpp_space_between_empty_braces = true
cpp_space_before_initializer_list_open_brace = false
cpp_space_within_initializer_list_braces = true
cpp_space_preserve_in_initializer_list = true
cpp_space_before_open_square_bracket = false
cpp_space_within_square_brackets = false
cpp_space_before_empty_square_brackets = false
cpp_space_between_empty_square_brackets = false
cpp_space_group_square_brackets = true
cpp_space_within_lambda_brackets = false
cpp_space_between_empty_lambda_brackets = false
cpp_space_before_comma = false
cpp_space_after_comma = true
cpp_space_remove_around_member_operators = true
cpp_space_before_inheritance_colon = true
cpp_space_before_constructor_colon = true
cpp_space_remove_before_semicolon = true
cpp_space_after_semicolon = true
cpp_space_remove_around_unary_operator = true
cpp_space_around_binary_operator = insert
cpp_space_around_assignment_operator = insert
cpp_space_pointer_reference_alignment = right
cpp_space_around_ternary_operator = insert
cpp_use_unreal_engine_macro_formatting = true
cpp_wrap_preserve_blocks = one_liners
# IDEA settings
ij_c_add_brief_tag = false
ij_c_add_getter_prefix = true
ij_c_add_setter_prefix = true
ij_c_align_dictionary_pair_values = false
ij_c_align_group_field_declarations = false
ij_c_align_init_list_in_columns = true
ij_c_align_multiline_array_initializer_expression = false
ij_c_align_multiline_assignment = false
ij_c_align_multiline_binary_operation = false
ij_c_align_multiline_chained_methods = false
ij_c_align_multiline_for = true
ij_c_align_multiline_ternary_operation = false
ij_c_array_initializer_comma_on_next_line = false
ij_c_array_initializer_new_line_after_left_brace = false
ij_c_array_initializer_right_brace_on_new_line = false
ij_c_array_initializer_wrap = off
ij_c_assignment_wrap = off
ij_c_binary_operation_sign_on_next_line = false
ij_c_binary_operation_wrap = off
ij_c_blank_lines_after_class_header = 0
ij_c_blank_lines_after_imports = 1
ij_c_blank_lines_around_class = 1
ij_c_blank_lines_around_field = 0
ij_c_blank_lines_around_field_in_interface = 0
ij_c_blank_lines_around_method = 1
ij_c_blank_lines_around_method_in_interface = 1
ij_c_blank_lines_around_namespace = 0
ij_c_blank_lines_around_properties_in_declaration = 0
ij_c_blank_lines_around_properties_in_interface = 0
ij_c_blank_lines_before_imports = 1
ij_c_blank_lines_before_method_body = 0
ij_c_block_brace_placement = next_line
ij_c_block_brace_style = next_line
ij_c_block_comment_at_first_column = true
ij_c_catch_on_new_line = false
ij_c_class_brace_style = next_line
ij_c_class_constructor_init_list_align_multiline = true
ij_c_class_constructor_init_list_comma_on_next_line = false
ij_c_class_constructor_init_list_new_line_after_colon = never
ij_c_class_constructor_init_list_new_line_before_colon = if_long
ij_c_class_constructor_init_list_wrap = normal
ij_c_copy_is_deep = false
ij_c_create_interface_for_categories = true
ij_c_declare_generated_methods = true
ij_c_description_include_member_names = true
ij_c_discharged_short_ternary_operator = false
ij_c_do_not_add_breaks = false
ij_c_do_while_brace_force = never
ij_c_else_on_new_line = false
ij_c_enum_constants_comma_on_next_line = false
ij_c_enum_constants_wrap = off
ij_c_for_brace_force = never
ij_c_for_statement_new_line_after_left_paren = false
ij_c_for_statement_right_paren_on_new_line = false
ij_c_for_statement_wrap = off
ij_c_function_brace_placement = next_line
ij_c_function_call_arguments_align_multiline = true
ij_c_function_call_arguments_align_multiline_pars = false
ij_c_function_call_arguments_comma_on_next_line = false
ij_c_function_call_arguments_new_line_after_lpar = false
ij_c_function_call_arguments_new_line_before_rpar = false
ij_c_function_call_arguments_wrap = normal
ij_c_function_non_top_after_return_type_wrap = normal
ij_c_function_parameters_align_multiline = true
ij_c_function_parameters_align_multiline_pars = false
ij_c_function_parameters_comma_on_next_line = false
ij_c_function_parameters_new_line_after_lpar = false
ij_c_function_parameters_new_line_before_rpar = false
ij_c_function_parameters_wrap = normal
ij_c_function_top_after_return_type_wrap = normal
ij_c_generate_additional_eq_operators = true
ij_c_generate_additional_rel_operators = true
ij_c_generate_class_constructor = true
ij_c_generate_comparison_operators_use_std_tie = false
ij_c_generate_instance_variables_for_properties = ask
ij_c_generate_operators_as_members = true
ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT}
ij_c_if_brace_force = never
ij_c_in_line_short_ternary_operator = true
ij_c_indent_block_comment = true
ij_c_indent_c_struct_members = 4
ij_c_indent_case_from_switch = true
ij_c_indent_class_members = 4
ij_c_indent_directive_as_code = false
ij_c_indent_implementation_members = 0
ij_c_indent_inside_code_block = 4
ij_c_indent_interface_members = 0
ij_c_indent_interface_members_except_ivars_block = false
ij_c_indent_namespace_members = 4
ij_c_indent_preprocessor_directive = 0
ij_c_indent_visibility_keywords = 0
ij_c_insert_override = true
ij_c_insert_virtual_with_override = false
ij_c_introduce_auto_consts = false
ij_c_introduce_auto_vars = false
ij_c_introduce_const_params = false
ij_c_introduce_const_vars = false
ij_c_introduce_constexpr_consts = false
ij_c_introduce_generate_property = false
ij_c_introduce_generate_synthesize = true
ij_c_introduce_globals_to_header = true
ij_c_introduce_prop_to_private_category = false
ij_c_introduce_static_consts = true
ij_c_introduce_use_ns_types = false
ij_c_ivars_prefix = _
ij_c_ivars_suffix =
ij_c_keep_blank_lines_before_end = 2
ij_c_keep_blank_lines_before_right_brace = 2
ij_c_keep_blank_lines_in_code = 2
ij_c_keep_blank_lines_in_declarations = 2
ij_c_keep_case_expressions_in_one_line = false
ij_c_keep_control_statement_in_one_line = false
ij_c_keep_directive_at_first_column = true
ij_c_keep_first_column_comment = false
ij_c_keep_line_breaks = true
ij_c_keep_nested_namespaces_in_one_line = false
ij_c_keep_simple_blocks_in_one_line = false
ij_c_keep_simple_methods_in_one_line = false
ij_c_keep_structures_in_one_line = false
ij_c_lambda_capture_list_align_multiline = false
ij_c_lambda_capture_list_align_multiline_bracket = false
ij_c_lambda_capture_list_comma_on_next_line = false
ij_c_lambda_capture_list_new_line_after_lbracket = false
ij_c_lambda_capture_list_new_line_before_rbracket = false
ij_c_lambda_capture_list_wrap = off
ij_c_line_comment_add_space = false
ij_c_line_comment_at_first_column = true
ij_c_method_brace_placement = end_of_line
ij_c_method_call_arguments_align_by_colons = true
ij_c_method_call_arguments_align_multiline = false
ij_c_method_call_arguments_special_dictionary_pairs_treatment = true
ij_c_method_call_arguments_wrap = off
ij_c_method_call_chain_wrap = off
ij_c_method_parameters_align_by_colons = true
ij_c_method_parameters_align_multiline = false
ij_c_method_parameters_wrap = off
ij_c_namespace_brace_placement = next_line
ij_c_parentheses_expression_new_line_after_left_paren = false
ij_c_parentheses_expression_right_paren_on_new_line = false
ij_c_place_assignment_sign_on_next_line = false
ij_c_property_nonatomic = true
ij_c_put_ivars_to_implementation = true
ij_c_refactor_compatibility_aliases_and_classes = true
ij_c_refactor_properties_and_ivars = true
ij_c_release_style = ivar
ij_c_retain_object_parameters_in_constructor = true
ij_c_semicolon_after_method_signature = false
ij_c_shift_operation_align_multiline = true
ij_c_shift_operation_wrap = normal
ij_c_show_non_virtual_functions = false
ij_c_space_after_colon = true
ij_c_space_after_colon_in_foreach = true
ij_c_space_after_colon_in_selector = false
ij_c_space_after_comma = true
ij_c_space_after_cup_in_blocks = false
ij_c_space_after_dictionary_literal_colon = true
ij_c_space_after_for_semicolon = true
ij_c_space_after_init_list_colon = true
ij_c_space_after_method_parameter_type_parentheses = false
ij_c_space_after_method_return_type_parentheses = false
ij_c_space_after_pointer_in_declaration = false
ij_c_space_after_quest = true
ij_c_space_after_reference_in_declaration = false
ij_c_space_after_reference_in_rvalue = false
ij_c_space_after_structures_rbrace = true
ij_c_space_after_superclass_colon = true
ij_c_space_after_type_cast = false
ij_c_space_after_visibility_sign_in_method_declaration = true
ij_c_space_before_autorelease_pool_lbrace = true
ij_c_space_before_catch_keyword = true
ij_c_space_before_catch_left_brace = true
ij_c_space_before_catch_parentheses = false
ij_c_space_before_category_parentheses = true
ij_c_space_before_chained_send_message = true
ij_c_space_before_class_left_brace = true
ij_c_space_before_colon = true
ij_c_space_before_colon_in_foreach = true
ij_c_space_before_comma = false
ij_c_space_before_dictionary_literal_colon = true
ij_c_space_before_do_left_brace = true
ij_c_space_before_else_keyword = true
ij_c_space_before_else_left_brace = true
ij_c_space_before_export_lbrace = true
ij_c_space_before_for_left_brace = true
ij_c_space_before_for_parentheses = false
ij_c_space_before_for_semicolon = false
ij_c_space_before_if_left_brace = true
ij_c_space_before_if_parentheses = false
ij_c_space_before_init_list = false
ij_c_space_before_init_list_colon = true
ij_c_space_before_method_call_parentheses = false
ij_c_space_before_method_left_brace = true
ij_c_space_before_method_parentheses = false
ij_c_space_before_namespace_lbrace = true
ij_c_space_before_pointer_in_declaration = true
ij_c_space_before_property_attributes_parentheses = false
ij_c_space_before_protocols_brackets = true
ij_c_space_before_quest = true
ij_c_space_before_reference_in_declaration = true
ij_c_space_before_superclass_colon = true
ij_c_space_before_switch_left_brace = true
ij_c_space_before_switch_parentheses = false
ij_c_space_before_template_call_lt = false
ij_c_space_before_template_declaration_lt = true
ij_c_space_before_try_left_brace = true
ij_c_space_before_while_keyword = true
ij_c_space_before_while_left_brace = true
ij_c_space_before_while_parentheses = false
ij_c_space_between_adjacent_brackets = false
ij_c_space_between_operator_and_punctuator = false
ij_c_space_within_empty_array_initializer_braces = true
ij_c_spaces_around_additive_operators = true
ij_c_spaces_around_assignment_operators = true
ij_c_spaces_around_bitwise_operators = true
ij_c_spaces_around_equality_operators = true
ij_c_spaces_around_lambda_arrow = true
ij_c_spaces_around_logical_operators = true
ij_c_spaces_around_multiplicative_operators = true
ij_c_spaces_around_pm_operators = false
ij_c_spaces_around_relational_operators = true
ij_c_spaces_around_shift_operators = true
ij_c_spaces_around_unary_operator = false
ij_c_spaces_within_array_initializer_braces = true
ij_c_spaces_within_braces = false
ij_c_spaces_within_brackets = false
ij_c_spaces_within_cast_parentheses = false
ij_c_spaces_within_catch_parentheses = true
ij_c_spaces_within_category_parentheses = false
ij_c_spaces_within_empty_braces = false
ij_c_spaces_within_empty_function_call_parentheses = true
ij_c_spaces_within_empty_function_declaration_parentheses = true
ij_c_spaces_within_empty_lambda_capture_list_bracket = false
ij_c_spaces_within_empty_template_call_ltgt = false
ij_c_spaces_within_empty_template_declaration_ltgt = false
ij_c_spaces_within_for_parentheses = true
ij_c_spaces_within_function_call_parentheses = true
ij_c_spaces_within_function_declaration_parentheses = true
ij_c_spaces_within_if_parentheses = true
ij_c_spaces_within_lambda_capture_list_bracket = false
ij_c_spaces_within_method_parameter_type_parentheses = false
ij_c_spaces_within_method_return_type_parentheses = false
ij_c_spaces_within_parentheses = true
ij_c_spaces_within_property_attributes_parentheses = false
ij_c_spaces_within_protocols_brackets = false
ij_c_spaces_within_send_message_brackets = false
ij_c_spaces_within_structured_binding_list_bracket = false
ij_c_spaces_within_switch_parentheses = true
ij_c_spaces_within_template_call_ltgt = false
ij_c_spaces_within_template_declaration_ltgt = false
ij_c_spaces_within_template_double_gt = false
ij_c_spaces_within_while_parentheses = true
ij_c_special_else_if_treatment = true
ij_c_structured_binding_list_align_multiline = false
ij_c_structured_binding_list_align_multiline_bracket = false
ij_c_structured_binding_list_comma_on_next_line = false
ij_c_structured_binding_list_new_line_after_lbracket = false
ij_c_structured_binding_list_new_line_before_rbracket = false
ij_c_structured_binding_list_wrap = off
ij_c_superclass_list_after_colon = never
ij_c_superclass_list_align_multiline = true
ij_c_superclass_list_before_colon = if_long
ij_c_superclass_list_comma_on_next_line = false
ij_c_superclass_list_wrap = on_every_item
ij_c_tag_prefix_of_block_comment = at
ij_c_tag_prefix_of_line_comment = back_slash
ij_c_template_call_arguments_align_multiline = false
ij_c_template_call_arguments_align_multiline_pars = false
ij_c_template_call_arguments_comma_on_next_line = false
ij_c_template_call_arguments_new_line_after_lt = false
ij_c_template_call_arguments_new_line_before_gt = false
ij_c_template_call_arguments_wrap = off
ij_c_template_declaration_function_body_indent = false
ij_c_template_declaration_function_wrap = split_into_lines
ij_c_template_declaration_struct_body_indent = false
ij_c_template_declaration_struct_wrap = split_into_lines
ij_c_template_parameters_align_multiline = false
ij_c_template_parameters_align_multiline_pars = false
ij_c_template_parameters_comma_on_next_line = false
ij_c_template_parameters_new_line_after_lt = false
ij_c_template_parameters_new_line_before_gt = false
ij_c_template_parameters_wrap = off
ij_c_ternary_operation_signs_on_next_line = false
ij_c_ternary_operation_wrap = off
ij_c_type_qualifiers_placement = before
ij_c_use_modern_casts = true
ij_c_use_setters_in_constructor = true
ij_c_while_brace_force = never
ij_c_while_on_new_line = false
ij_c_wrap_property_declaration = off

1
.github/FUNDING.yml vendored
View File

@@ -1 +0,0 @@
custom: https://github.com/FWGS/xash3d-fwgs/blob/master/Documentation/donate.md

View File

@@ -43,82 +43,80 @@ jobs:
- os: windows-2019 # always use the oldest possible for 32-bit because of older compilers, and better support of certain legacy OSes
targetos: win32
targetarch: i386
- os: macos-14 # in GitHub documentation, it's an ARM64 machine
targetos: apple
targetarch: arm64
- os: macos-12 # in GitHub documentation, it's an x86 machine
targetos: apple
targetarch: amd64
env:
SDL_VERSION: 2.30.3
SDL_VERSION: 2.28.5
GH_CPU_ARCH: ${{ matrix.targetarch }}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install dependencies
run: bash scripts/gha/deps_${{ matrix.targetos }}.sh
- name: Build engine
env:
FWGS_PFX_PASSWORD: ${{ secrets.FWGS_PFX_PASSWORD }}
run: bash scripts/gha/build_${{ matrix.targetos }}.sh
- name: Upload engine (artifacts)
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
path: artifacts/*
flatpak:
name: "Flatpak"
runs-on: ubuntu-latest
strategy:
matrix:
include:
- app: su.xash.Engine.Compat.i386
container:
image: bilelmoussaoui/flatpak-github-actions:freedesktop-23.08
image: bilelmoussaoui/flatpak-github-actions:freedesktop-22.08
options: --privileged
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
submodules: recursive
- name: Build flatpak (Compat.i386)
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.3
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.1
with:
bundle: ${{ matrix.app }}.flatpak
manifest-path: scripts/flatpak/${{ matrix.app }}.yml
- name: Upload engine (artifacts)
uses: actions/upload-artifact@v3
with:
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
path: artifacts/*
release:
name: "Upload releases"
runs-on: ubuntu-latest
needs: [build, flatpak]
if: ${{ github.event_name == 'push' }}
steps:
- name: Remove old release, fetch artifacts, repackage binaries and upload new release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
- name: Remove old release
uses: FWGS/delete-tag-and-release@v0.2.1-dev
with:
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
delete_release: true
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Fetch artifacts
uses: actions/download-artifact@v3.0.1
with:
path: artifacts/
- name: Repackage binaries and allow GitHub to process removed release for few seconds
run: |
gh release delete "$RELEASE_TAG" \
--yes \
--cleanup-tag \
--repo "$GITHUB_REPOSITORY" || true
sleep 20s
gh run download "$GITHUB_RUN_ID" \
--dir artifacts/ \
--repo "$GITHUB_REPOSITORY"
pushd artifacts/
echo "Found artifacts:"
ls
for i in $(find -mindepth 1 -maxdepth 1 -type d); do
cd artifacts/
for i in artifact-* su.xash.Engine.*; do
mv "$i"/* .
rm -rf "$i"
done
echo "Repackaged artifacts:"
ls -R
popd
ls -R .
cd ../
sleep 20s
gh release create "$RELEASE_TAG" artifacts/* \
--title "Xash3D FWGS Continuous ${{ github.ref_name }} Build" \
--target $GITHUB_SHA \
--repo "$GITHUB_REPOSITORY" \
--prerelease
- name: Upload new release
uses: FWGS/action-gh-release@v0.1.15
with:
name: Xash3D FWGS Continuous ${{ github.ref_name }} Build
tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
prerelease: true
token: ${{ secrets.GITHUB_TOKEN }}
files: artifacts/*
draft: false

3
.gitmodules vendored
View File

@@ -19,6 +19,3 @@
[submodule "3rdparty/xash-extras"]
path = 3rdparty/extras/xash-extras
url = https://github.com/FWGS/xash-extras
[submodule "3rdparty/bzip2/bzip2"]
path = 3rdparty/bzip2/bzip2
url = https://gitlab.com/bzip2/bzip2

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2017-2018 Alexander Belkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,25 +0,0 @@
# MultiEmulator
**MultiEmulator** - project for GoldSource Engine, which provides ability to generate tickets with a specific SteamID key, using all available emulators for this engine.
Ticket is processed by the game server of Half-Life 1 and modifications using **DProto** or **ReUnion** modules. If the server does not have these modules, then MultiEmulator won't work.
# Ticket generators
Currently available ticket generators:
* OldRevEmu
* AVSMP
* Setti
* SteamEmu
* RevEmu
* SC2009
* RevEmu2013
Currently under development generators:
* SmartSteamEmu (SSE3)
# How to use?
Each file in the **MultiEmulator\Source\Emulators** folder contains a **Generate** function that writes a ticket to the **pDest** argument for the emulator of the same name as a header file. As a result of the function, the size of the written ticket is returned. If the generator can set an arbitrary SteamID, the function will have the **nSteamID** argument, in which the required SteamID is specified.
# Examples
As an example, the DLL was developed that searches InitiateGameConnection method in ISteamUser interface, which generates Steam ticket, and inserts in its place own generator, which creates RevEmu2013 ticket with SteamID equal to 3333333. You can find this project in **Example** folder, you just need to compile it and perform DLL injection in hl.exe process with any known injection method.

View File

@@ -1,37 +0,0 @@
#ifndef MULTI_EMULATOR_H
#define MULTI_EMULATOR_H
#if defined( __GNUC__ )
#if defined( __i386__ )
#define ME_EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
#else
#define ME_EXPORT __attribute__(( visibility ( "default" )))
#endif
#else
#if defined( _MSC_VER )
#define ME_EXPORT __declspec( dllexport )
#else
#define ME_EXPORT
#endif
#endif
#include <string.h>
#if __cplusplus
extern "C"
{
#endif
int ME_EXPORT GenerateRevEmu2013( void *pDest, int nSteamID );
int ME_EXPORT GenerateSC2009( void *pDest, int nSteamID );
int ME_EXPORT GenerateOldRevEmu( void *pDest, int nSteamID );
int ME_EXPORT GenerateSteamEmu( void *pDest, int nSteamID );
int ME_EXPORT GenerateRevEmu( void *pDest, int nSteamID );
int ME_EXPORT GenerateSetti( void *pDest );
int ME_EXPORT GenerateAVSMP( void *pDest, int nSteamID, int bUniverse );
#if __cplusplus
}
#endif
#endif // MULTI_EMULATOR_H

View File

@@ -1,13 +0,0 @@
#include "multi_emulator.h"
/* bUniverse param is "y" value in "STEAM_x:y:z" */
int GenerateAVSMP(void *pDest, int nSteamID, int bUniverse)
{
auto pTicket = (int *)pDest;
pTicket[0] = 0x14; // +0, header
pTicket[3] = (nSteamID << 1) | (bUniverse ? 1 : 0); // +12, SteamId, Low part
pTicket[4] = 0x01100001; // +16, SteamId, High part
return 28;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,187 +0,0 @@
#ifndef __RIJNDAEL_H__
#define __RIJNDAEL_H__
#include <exception>
#include <stdexcept>
#include <cstring>
#include <string>
using namespace std;
//Rijndael (pronounced Reindaal) is a block cipher, designed by Joan Daemen and Vincent Rijmen as a candidate algorithm for the AES.
//The cipher has a variable block length and key length. The authors currently specify how to use keys with a length
//of 128, 192, or 256 bits to encrypt blocks with al length of 128, 192 or 256 bits (all nine combinations of
//key length and block length are possible). Both block length and key length can be extended very easily to
// multiples of 32 bits.
//Rijndael can be implemented very efficiently on a wide range of processors and in hardware.
//This implementation is based on the Java Implementation used with the Cryptix toolkit found at:
//http://www.esat.kuleuven.ac.be/~rijmen/rijndael/rijndael.zip
//Java code authors: Raif S. Naffah, Paulo S. L. M. Barreto
//This Implementation was tested against KAT test published by the authors of the method and the
//results were identical.
class CRijndael
{
public:
//Operation Modes
//The Electronic Code Book (ECB), Cipher Block Chaining (CBC) and Cipher Feedback Block (CFB) modes
//are implemented.
//In ECB mode if the same block is encrypted twice with the same key, the resulting
//ciphertext blocks are the same.
//In CBC Mode a ciphertext block is obtained by first xoring the
//plaintext block with the previous ciphertext block, and encrypting the resulting value.
//In CFB mode a ciphertext block is obtained by encrypting the previous ciphertext block
//and xoring the resulting value with the plaintext.
enum { ECB = 0, CBC = 1, CFB = 2 };
private:
enum { DEFAULT_BLOCK_SIZE = 16 };
enum { MAX_BLOCK_SIZE = 32, MAX_ROUNDS = 14, MAX_KC = 8, MAX_BC = 8 };
//Auxiliary Functions
//Multiply two elements of GF(2^m)
static int Mul(int a, int b)
{
return (a != 0 && b != 0) ? sm_alog[(sm_log[a & 0xFF] + sm_log[b & 0xFF]) % 255] : 0;
}
//Convenience method used in generating Transposition Boxes
static int Mul4(int a, char b[])
{
if (a == 0)
return 0;
a = sm_log[a & 0xFF];
int a0 = (b[0] != 0) ? sm_alog[(a + sm_log[b[0] & 0xFF]) % 255] & 0xFF : 0;
int a1 = (b[1] != 0) ? sm_alog[(a + sm_log[b[1] & 0xFF]) % 255] & 0xFF : 0;
int a2 = (b[2] != 0) ? sm_alog[(a + sm_log[b[2] & 0xFF]) % 255] & 0xFF : 0;
int a3 = (b[3] != 0) ? sm_alog[(a + sm_log[b[3] & 0xFF]) % 255] & 0xFF : 0;
return a0 << 24 | a1 << 16 | a2 << 8 | a3;
}
public:
//CONSTRUCTOR
CRijndael();
//DESTRUCTOR
virtual ~CRijndael();
//Expand a user-supplied key material into a session key.
// key - The 128/192/256-bit user-key to use.
// chain - initial chain block for CBC and CFB modes.
// keylength - 16, 24 or 32 bytes
// blockSize - The block size in bytes of this Rijndael (16, 24 or 32 bytes).
void MakeKey(char const* key, char const* chain, int keylength = DEFAULT_BLOCK_SIZE, int blockSize = DEFAULT_BLOCK_SIZE);
private:
//Auxiliary Function
void Xor(char* buff, char const* chain)
{
if (false == m_bKeyInit)
throw runtime_error(sm_szErrorMsg1);
for (int i = 0; i<m_blockSize; i++)
*(buff++) ^= *(chain++);
}
//Convenience method to encrypt exactly one block of plaintext, assuming
//Rijndael's default block size (128-bit).
// in - The plaintext
// result - The ciphertext generated from a plaintext using the key
void DefEncryptBlock(char const* in, char* result);
//Convenience method to decrypt exactly one block of plaintext, assuming
//Rijndael's default block size (128-bit).
// in - The ciphertext.
// result - The plaintext generated from a ciphertext using the session key.
void DefDecryptBlock(char const* in, char* result);
public:
//Encrypt exactly one block of plaintext.
// in - The plaintext.
// result - The ciphertext generated from a plaintext using the key.
void EncryptBlock(char const* in, char* result);
//Decrypt exactly one block of ciphertext.
// in - The ciphertext.
// result - The plaintext generated from a ciphertext using the session key.
void DecryptBlock(char const* in, char* result);
void Encrypt(char const* in, char* result, size_t n, int iMode = ECB);
void Decrypt(char const* in, char* result, size_t n, int iMode = ECB);
//Get Key Length
int GetKeyLength()
{
if (false == m_bKeyInit)
throw runtime_error(sm_szErrorMsg1);
return m_keylength;
}
//Block Size
int GetBlockSize()
{
if (false == m_bKeyInit)
throw runtime_error(sm_szErrorMsg1);
return m_blockSize;
}
//Number of Rounds
int GetRounds()
{
if (false == m_bKeyInit)
throw runtime_error(sm_szErrorMsg1);
return m_iROUNDS;
}
void ResetChain()
{
memcpy(m_chain, m_chain0, m_blockSize);
}
public:
//Null chain
static char const* sm_chain0;
private:
static const int sm_alog[256];
static const int sm_log[256];
static const char sm_S[256];
static const char sm_Si[256];
static const int sm_T1[256];
static const int sm_T2[256];
static const int sm_T3[256];
static const int sm_T4[256];
static const int sm_T5[256];
static const int sm_T6[256];
static const int sm_T7[256];
static const int sm_T8[256];
static const int sm_U1[256];
static const int sm_U2[256];
static const int sm_U3[256];
static const int sm_U4[256];
static const char sm_rcon[30];
static const int sm_shifts[3][4][2];
//Error Messages
static char const* sm_szErrorMsg1;
static char const* sm_szErrorMsg2;
//Key Initialization Flag
bool m_bKeyInit;
//Encryption (m_Ke) round key
int m_Ke[MAX_ROUNDS + 1][MAX_BC];
//Decryption (m_Kd) round key
int m_Kd[MAX_ROUNDS + 1][MAX_BC];
//Key Length
int m_keylength;
//Block Size
int m_blockSize;
//Number of Rounds
int m_iROUNDS;
//Chain Block
char m_chain0[MAX_BLOCK_SIZE];
char m_chain[MAX_BLOCK_SIZE];
//Auxiliary private use buffers
int tk[MAX_KC];
int a[MAX_BC];
int t[MAX_BC];
};
#endif // __RIJNDAEL_H__

View File

@@ -1,128 +0,0 @@
//DoubleBuffering.cpp Source File
#include "DoubleBuffering.h"
#include <cassert>
#include <exception>
#include <string.h>
using namespace std;
CDoubleBuffering::CDoubleBuffering(ifstream& in, char* pcBuff, int iSize, int iDataLen) : m_rin(in),
m_iDataLen(iDataLen), m_bEOF(false), m_iSize(iSize), m_iSize2(iSize >> 1), m_pcBuff(pcBuff)
{
//m_iSize should be even
if(m_iSize%2 != 0)
throw runtime_error("CDoubleBuffering: m_iSize should be Even Number!");
//Check file
if(!in.is_open() || in.bad())
throw runtime_error("CDoubleBuffering: Referenced File not Opened or in Bad State!");
//Check construction data
if(m_iDataLen<1 || m_iSize2<m_iDataLen)
throw runtime_error("CDoubleBuffering: Illegal Construction Data!");
in.read(m_pcBuff, m_iSize2);
m_iEnd = m_rin.gcount();
m_iCurPos = 0;
m_iBuf = 0;
}
int CDoubleBuffering::GetData(char* pszDataBuf, int iDataLen)
{
if(-1 == iDataLen)
iDataLen = m_iDataLen;
if(iDataLen<1 || m_iSize2<iDataLen)
throw runtime_error("CDoubleBuffering::GetData(): Illegal iDataLen!");
if(true == m_bEOF)
return 0;
//Estimate the next position
int iCurPos = m_iCurPos + iDataLen;
if(0 == m_iBuf) //First Buffer
{
if(iCurPos >= m_iEnd)
{
//Read the next buffer
if(m_rin.eof())
{
m_bEOF = true;
//Take everything remained
int iRead = m_iEnd-m_iCurPos;
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
return iRead;
}
else
{
m_rin.read(m_pcBuff+m_iEnd, m_iSize2);
m_iEnd += m_rin.gcount();
if(iCurPos > m_iEnd) //Still greater, then EOF attained
{
assert(m_rin.eof());
m_bEOF = true;
//Take everything remained
int iRead = m_iEnd-m_iCurPos;
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
return iRead;
}
else
{
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iDataLen);
m_iCurPos = iCurPos;
assert(m_iCurPos >= m_iSize2);
m_iBuf = 1;
return iDataLen;
}
}
}
else
{
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iDataLen);
m_iCurPos = iCurPos;
return iDataLen;
}
}
else //1 == m_iBuf, Second Buffer
{
if(iCurPos >= m_iEnd)
{
//Read the next buffer
if(m_rin.eof())
{
m_bEOF = true;
//Take everything remained
int iRead = m_iEnd-m_iCurPos;
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
return iRead;
}
else
{
m_rin.read(m_pcBuff, m_iSize2);
m_iEnd = m_rin.gcount();
iCurPos %= m_iSize;
if(iCurPos > m_iEnd) //Still greater, then EOF attained
{
assert(m_rin.eof());
m_bEOF = true;
//Take everything remained
int iRead = m_iSize-m_iCurPos;
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
memcpy(pszDataBuf+iRead, m_pcBuff, m_iEnd);
return iRead + m_iEnd;
}
else
{
int iRead = m_iSize-m_iCurPos;
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iRead);
memcpy(pszDataBuf+iRead, m_pcBuff, iDataLen-iRead);
m_iCurPos = iCurPos;
assert(m_iCurPos < m_iSize2);
m_iBuf = 0;
return iDataLen;
}
}
}
else
{
memcpy(pszDataBuf, m_pcBuff+m_iCurPos, iDataLen);
m_iCurPos = iCurPos;
return iDataLen;
}
}
}

View File

@@ -1,40 +0,0 @@
//DoubleBuffering.h Header File
#ifndef __DOUBLEBUFFERING_H__
#define __DOUBLEBUFFERING_H__
//Typical DISCLAIMER:
//The code in this project is Copyright (C) 2003 by George Anescu. You have the right to
//use and distribute the code in any way you see fit as long as this paragraph is included
//with the distribution. No warranties or claims are made as to the validity of the
//information and code contained herein, so use it at your own risk.
#include <fstream>
using namespace std;
class CDoubleBuffering
{
public:
//Constructor
CDoubleBuffering(ifstream& in, char* pcBuff, int iSize, int iDataLen);
//Get Next Data Buffer
int GetData(char* pszDataBuf, int iDataLen=-1);
private:
ifstream& m_rin;
int m_iSize;
int m_iSize2; //m_iSize/2
int m_iDataLen;
//Current Position
int m_iCurPos;
//End Position
int m_iEnd;
//Which Buffer
int m_iBuf;
char* m_pcBuff;
//EOF attained
bool m_bEOF;
};
#endif //__DOUBLEBUFFERING_H__

View File

@@ -1,38 +0,0 @@
//MessageDigest.cpp
#include "MessageDigest.h"
#include "DoubleBuffering.h"
#include <exception>
#include <fstream>
#include <strstream>
using namespace std;
//Digesting a Full File
void IMessageDigest::DigestFile(string const& rostrFileIn, char* pcDigest)
{
//Is the User's responsability to ensure that pcDigest is appropriately allocated
//Open Input File
ifstream in(rostrFileIn.c_str(), ios::binary);
if(!in)
{
ostrstream ostr;
ostr << "FileDigest ERROR: in IMessageDigest::DigestFile(): Cannot open File " << rostrFileIn << "!" << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
//Resetting first
Reset();
//Reading from file
char szLargeBuff[BUFF_LEN+1] = {0};
char szBuff[DATA_LEN+1] = {0};
CDoubleBuffering oDoubleBuffering(in, szLargeBuff, BUFF_LEN, DATA_LEN);
int iRead;
while((iRead=oDoubleBuffering.GetData(szBuff)) > 0)
AddData(szBuff, iRead);
in.close();
//Final Step
FinalDigest(pcDigest);
}

View File

@@ -1,47 +0,0 @@
//MessageDigest.h
#ifndef __MESSAGEDIGEST_H__
#define __MESSAGEDIGEST_H__
#include <string>
using namespace std;
//Typical DISCLAIMER:
//The code in this project is Copyright (C) 2003 by George Anescu. You have the right to
//use and distribute the code in any way you see fit as long as this paragraph is included
//with the distribution. No warranties or claims are made as to the validity of the
//information and code contained herein, so use it at your own risk.
//General Message Digest Interface
class IMessageDigest
{
public:
//CONSTRUCTOR
IMessageDigest() : m_bAddData(false) {}
//DESTRUCTOR
virtual ~IMessageDigest() {}
//Update context to reflect the concatenation of another buffer of bytes
virtual void AddData(char const* pcData, int iDataLength) = 0;
//Final wrapup - pad to BLOCKSIZE-byte boundary with the bit pattern
//10000...(64-bit count of bits processed, MSB-first)
virtual void FinalDigest(char* pcDigest) = 0;
//Reset current operation in order to prepare for a new one
virtual void Reset() = 0;
//Digesting a Full File
void DigestFile(string const& rostrFileIn, char* pcDigest);
protected:
enum { BLOCKSIZE=64 };
//Control Flag
bool m_bAddData;
//The core of the MessageDigest algorithm, this alters an existing MessageDigest hash to
//reflect the addition of 64 bytes of new data
virtual void Transform() = 0;
private:
enum { DATA_LEN=384, BUFF_LEN=1024 };
};
#endif // __MESSAGEDIGEST_H__

View File

@@ -1,13 +0,0 @@
#include "multi_emulator.h"
int GenerateOldRevEmu(void* pDest, int nSteamID)
{
auto pTicket = (int*)pDest;
auto pbTicket = (unsigned char*)pDest;
pTicket[0] = 0xFFFF; // +0, header
pTicket[1] = (nSteamID ^ 0xC9710266) << 1; // +4, SteamId
*(short *)&pbTicket[8] = 0; // +8, unknown, in original emulator must be 0
return 10;
}

View File

@@ -1,27 +0,0 @@
#include "multi_emulator.h"
#include "StrUtils.h"
#include "RevSpoofer.h"
int GenerateRevEmu(void *pDest, int nSteamID)
{
char szhwid[64];
CreateRandomString(szhwid, 16);
if (!RevSpoofer::Spoof(szhwid, nSteamID))
return 0;
auto pTicket = (int *)pDest;
auto revHash = RevSpoofer::Hash(szhwid);
pTicket[0] = 'J'; // +0, header
pTicket[1] = revHash; // +4, hash of string at +24 offset
pTicket[2] = 'r' << 16 | 'e' << 8 | 'v';// +8, magic number
pTicket[3] = 0; // +12, unknown number, must always be 0
pTicket[4] = revHash << 1; // +16, SteamId, Low part
pTicket[5] = 0x01100001; // +20, SteamId, High part
strcpy((char *)&pTicket[6], szhwid); // +24, string for hash
return 152;
}

View File

@@ -1,55 +0,0 @@
#include "multi_emulator.h"
#include "StrUtils.h"
#include "RevSpoofer.h"
#include "CRijndael.h"
#include "SHA.h"
#include <time.h>
int GenerateRevEmu2013(void *pDest, int nSteamID)
{
char szhwid[64];
CreateRandomString(szhwid, 32);
if (!RevSpoofer::Spoof(szhwid, nSteamID))
return 0;
auto pTicket = (int *)pDest;
auto pbTicket = (unsigned char *)pDest;
auto revHash = RevSpoofer::Hash(szhwid);
pTicket[0] = 'S'; // +0
pTicket[1] = revHash; // +4
pTicket[2] = 'r' << 16 | 'e' << 8 | 'v';;// +8
pTicket[3] = 0; // +12
pTicket[4] = revHash << 1; // +16
pTicket[5] = 0x01100001; // +20
pTicket[6] = (int)time(0) + 90123; // +24
pbTicket[27] = ~(pbTicket[27] + pbTicket[24]);
pTicket[7] = ~(int)time(0); // +28
pTicket[8] = revHash * 2 >> 3; // +32
pTicket[9] = 0; // +36
static const char c_szAESKeyRand[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
char szAESHashRand[32];
auto AESRand = CRijndael();
AESRand.MakeKey(c_szAESKeyRand, CRijndael::sm_chain0, 32, 32);
AESRand.EncryptBlock(szhwid, szAESHashRand);
memcpy(&pbTicket[40], szAESHashRand, 32);
static const char c_szAESKeyRev[] = "_YOU_SERIOUSLY_NEED_TO_GET_LAID_";
char AESHashRev[32];
auto AESRev = CRijndael();
AESRev.MakeKey(c_szAESKeyRev, CRijndael::sm_chain0, 32, 32);
AESRev.EncryptBlock(c_szAESKeyRand, AESHashRev);
memcpy(&pbTicket[72], AESHashRev, 32);
char szSHAHash[32];
auto sha = CSHA(CSHA::SHA256);
sha.AddData(szhwid, 32);
sha.FinalDigest(szSHAHash);
memcpy(&pbTicket[104], szSHAHash, 32);
return 194;
}

View File

@@ -1,96 +0,0 @@
#include "RevSpoofer.h"
#include <string.h>
#define astrlen(x) sizeof(x) - 1
static char s_szDictionary[] = { "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" };
static int iInputLen;
static unsigned int uTreasure;
bool ScanLast3(char *pszInput, unsigned int uPrevHash)
{
unsigned int h1, h2, h3, hh;
for (int i1 = 0; i1 < astrlen(s_szDictionary); i1++)
{
h1 = uPrevHash ^ ((uPrevHash >> 2) + (uPrevHash << 5) + s_szDictionary[i1]);
hh = h1 ^ ((h1 >> 2) + (h1 << 5));
hh = hh ^ ((hh >> 2) + (hh << 5));
if ((hh ^ uTreasure) >> (8 + 5 + 3))
continue;
for (int i2 = 0; i2 < astrlen(s_szDictionary); i2++)
{
h2 = h1 ^ ((h1 >> 2) + (h1 << 5) + s_szDictionary[i2]);
hh = h2 ^ ((h2 >> 2) + (h2 << 5));
if ((hh ^ uTreasure) >> (8 + 3))
continue;
for (int i3 = 0; i3 < astrlen(s_szDictionary); i3++)
{
h3 = h2 ^ ((h2 >> 2) + (h2 << 5) + s_szDictionary[i3]);
if (h3 == uTreasure)
{
pszInput[iInputLen - 3] = s_szDictionary[i1];
pszInput[iInputLen - 2] = s_szDictionary[i2];
pszInput[iInputLen - 1] = s_szDictionary[i3];
return true;
}
}
}
}
return false;
}
bool ScanNext(char* pszInput, int uIndex, unsigned int uPrevHash)
{
bool res;
for (int i = 0; i < astrlen(s_szDictionary); i++)
{
auto h = uPrevHash ^ ((uPrevHash >> 2) + (uPrevHash << 5) + s_szDictionary[i]);
if (uIndex + 1 < iInputLen - 3)
res = ScanNext(pszInput, uIndex + 1, h);
else
res = ScanLast3(pszInput, h);
if (res)
{
pszInput[uIndex] = s_szDictionary[i];
return true;
}
}
return false;
}
namespace RevSpoofer
{
bool Spoof(char *pszDest, int uSID)
{
uTreasure = uSID;
iInputLen = strlen(pszDest);
auto i = iInputLen - 7;
i = (i < 0) ? 0 : i;
pszDest[i] = '\0';
auto h = Hash(pszDest);
return ScanNext(pszDest, i, h);
}
unsigned int Hash(char *pszString)
{
int i = 0;
unsigned int nHash = 0x4E67C6A7;
int c = pszString[i++];
while (c)
{
nHash = nHash ^ ((nHash >> 2) + (nHash << 5) + c);
c = pszString[i++];
}
return nHash;
}
}

View File

@@ -1,7 +0,0 @@
#pragma once
namespace RevSpoofer
{
bool Spoof(char *pszDest, int uSID);
unsigned int Hash(char *pszString);
}

View File

@@ -1,52 +0,0 @@
#include "multi_emulator.h"
#include "StrUtils.h"
#include "RevSpoofer.h"
#include "CRijndael.h"
#include "SHA.h"
int GenerateSC2009(void* pDest, int nSteamID)
{
char hwid[64];
CreateRandomString(hwid, 32);
if (!RevSpoofer::Spoof(hwid, nSteamID))
return 0;
auto pTicket = (int*)pDest;
auto pbTicket = (unsigned char*)pDest;
auto revHash = RevSpoofer::Hash(hwid);
pTicket[0] = 'S'; // +0
pTicket[1] = revHash; // +4
pTicket[2] = 'r' << 16 | 'e' << 8 | 'v';;// +8
pTicket[3] = 0; // +12
pTicket[4] = revHash << 1; // +16
pTicket[5] = 0x01100001; // +20
/* Encrypt HWID with AESKeyRand key and save it in the ticket. */
static const char AESKeyRand[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
char AESHashRand[32];
auto AESRand = CRijndael();
AESRand.MakeKey(AESKeyRand, CRijndael::sm_chain0, 32, 32);
AESRand.EncryptBlock(hwid, AESHashRand);
memcpy(&pbTicket[24], AESHashRand, 32);
/* Encrypt AESKeyRand with AESKeyRev key and save it in the ticket.
* AESKeyRev key is identical to the key in dproto/reunion. */
static const char AESKeyRev[] = "_YOU_SERIOUSLY_NEED_TO_GET_LAID_";
char AESHashRev[32];
auto AESRev = CRijndael();
AESRev.MakeKey(AESKeyRev, CRijndael::sm_chain0, 32, 32);
AESRev.EncryptBlock(AESKeyRand, AESHashRev);
memcpy(&pbTicket[56], AESHashRev, 32);
/* Perform HWID hashing and save hash to the ticket. */
char SHAHash[32];
auto sha = CSHA(CSHA::SHA256);
sha.AddData(hwid, 32);
sha.FinalDigest(SHAHash);
memcpy(&pbTicket[88], SHAHash, 32);
return 178;
}

View File

@@ -1,734 +0,0 @@
//SHA.cpp
#include "SHA.h"
#include <exception>
#include <strstream>
#include <string.h>
using namespace std;
const unsigned int CSHA::sm_K160[4] =
{
0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
};
const unsigned int CSHA::sm_H160[SHA160LENGTH] =
{
0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
};
const unsigned int CSHA::sm_K256[64] =
{
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
const unsigned int CSHA::sm_H256[SHA256LENGTH] =
{
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
};
const SUI64 CSHA::sm_H384[SHA512LENGTH] =
{
{0xcbbb9d5d, 0xc1059ed8},
{0x629a292a, 0x367cd507},
{0x9159015a, 0x3070dd17},
{0x152fecd8, 0xf70e5939},
{0x67332667, 0xffc00b31},
{0x8eb44a87, 0x68581511},
{0xdb0c2e0d, 0x64f98fa7},
{0x47b5481d, 0xbefa4fa4}
};
const SUI64 CSHA::sm_K512[80] =
{
{0x428a2f98, 0xd728ae22}, {0x71374491, 0x23ef65cd},
{0xb5c0fbcf, 0xec4d3b2f}, {0xe9b5dba5, 0x8189dbbc},
{0x3956c25b, 0xf348b538}, {0x59f111f1, 0xb605d019},
{0x923f82a4, 0xaf194f9b}, {0xab1c5ed5, 0xda6d8118},
{0xd807aa98, 0xa3030242}, {0x12835b01, 0x45706fbe},
{0x243185be, 0x4ee4b28c}, {0x550c7dc3, 0xd5ffb4e2},
{0x72be5d74, 0xf27b896f}, {0x80deb1fe, 0x3b1696b1},
{0x9bdc06a7, 0x25c71235}, {0xc19bf174, 0xcf692694},
{0xe49b69c1, 0x9ef14ad2}, {0xefbe4786, 0x384f25e3},
{0x0fc19dc6, 0x8b8cd5b5}, {0x240ca1cc, 0x77ac9c65},
{0x2de92c6f, 0x592b0275}, {0x4a7484aa, 0x6ea6e483},
{0x5cb0a9dc, 0xbd41fbd4}, {0x76f988da, 0x831153b5},
{0x983e5152, 0xee66dfab}, {0xa831c66d, 0x2db43210},
{0xb00327c8, 0x98fb213f}, {0xbf597fc7, 0xbeef0ee4},
{0xc6e00bf3, 0x3da88fc2}, {0xd5a79147, 0x930aa725},
{0x06ca6351, 0xe003826f}, {0x14292967, 0x0a0e6e70},
{0x27b70a85, 0x46d22ffc}, {0x2e1b2138, 0x5c26c926},
{0x4d2c6dfc, 0x5ac42aed}, {0x53380d13, 0x9d95b3df},
{0x650a7354, 0x8baf63de}, {0x766a0abb, 0x3c77b2a8},
{0x81c2c92e, 0x47edaee6}, {0x92722c85, 0x1482353b},
{0xa2bfe8a1, 0x4cf10364}, {0xa81a664b, 0xbc423001},
{0xc24b8b70, 0xd0f89791}, {0xc76c51a3, 0x0654be30},
{0xd192e819, 0xd6ef5218}, {0xd6990624, 0x5565a910},
{0xf40e3585, 0x5771202a}, {0x106aa070, 0x32bbd1b8},
{0x19a4c116, 0xb8d2d0c8}, {0x1e376c08, 0x5141ab53},
{0x2748774c, 0xdf8eeb99}, {0x34b0bcb5, 0xe19b48a8},
{0x391c0cb3, 0xc5c95a63}, {0x4ed8aa4a, 0xe3418acb},
{0x5b9cca4f, 0x7763e373}, {0x682e6ff3, 0xd6b2b8a3},
{0x748f82ee, 0x5defb2fc}, {0x78a5636f, 0x43172f60},
{0x84c87814, 0xa1f0ab72}, {0x8cc70208, 0x1a6439ec},
{0x90befffa, 0x23631e28}, {0xa4506ceb, 0xde82bde9},
{0xbef9a3f7, 0xb2c67915}, {0xc67178f2, 0xe372532b},
{0xca273ece, 0xea26619c}, {0xd186b8c7, 0x21c0c207},
{0xeada7dd6, 0xcde0eb1e}, {0xf57d4f7f, 0xee6ed178},
{0x06f067aa, 0x72176fba}, {0x0a637dc5, 0xa2c898a6},
{0x113f9804, 0xbef90dae}, {0x1b710b35, 0x131c471b},
{0x28db77f5, 0x23047d84}, {0x32caab7b, 0x40c72493},
{0x3c9ebe0a, 0x15c9bebc}, {0x431d67c4, 0x9c100d4c},
{0x4cc5d4be, 0xcb3e42b6}, {0x597f299c, 0xfc657e2a},
{0x5fcb6fab, 0x3ad6faec}, {0x6c44198c, 0x4a475817}
};
const SUI64 CSHA::sm_H512[SHA512LENGTH] =
{
{0x6a09e667, 0xf3bcc908},
{0xbb67ae85, 0x84caa73b},
{0x3c6ef372, 0xfe94f82b},
{0xa54ff53a, 0x5f1d36f1},
{0x510e527f, 0xade682d1},
{0x9b05688c, 0x2b3e6c1f},
{0x1f83d9ab, 0xfb41bd6b},
{0x5be0cd19, 0x137e2179}
};
//CONSTRUCTOR
CSHA::CSHA(int iMethod)
{
//Check the method
switch(iMethod)
{
case SHA160:
{
for(int i=0; i<SHA160LENGTH; i++)
m_auiBuf[i] = sm_H160[i];
m_auiBits[0] = 0;
m_auiBits[1] = 0;
}
break;
case SHA256:
{
for(int i=0; i<SHA256LENGTH; i++)
m_auiBuf[i] = sm_H256[i];
m_auiBits[0] = 0;
m_auiBits[1] = 0;
}
break;
case SHA384:
{
for(int i=0; i<SHA512LENGTH; i++)
m_aoui64Buf[i] = sm_H384[i];
m_aoui64Bits[0].m_uiLeft = 0;
m_aoui64Bits[0].m_uiRight = 0;
m_aoui64Bits[1].m_uiLeft = 0;
m_aoui64Bits[1].m_uiRight = 0;
}
break;
case SHA512:
{
for(int i=0; i<SHA512LENGTH; i++)
m_aoui64Buf[i] = sm_H512[i];
m_aoui64Bits[0].m_uiLeft = 0;
m_aoui64Bits[0].m_uiRight = 0;
m_aoui64Bits[1].m_uiLeft = 0;
m_aoui64Bits[1].m_uiRight = 0;
}
break;
default:
{
ostrstream ostr;
ostr << "FileDigest ERROR: in CSHA() Constructor, Illegal Method " << iMethod << "!" << ends;
string ostrMsg = ostr.str();
ostr.freeze(false);
throw runtime_error(ostrMsg);
}
}
m_iMethod = iMethod;
}
//Update context to reflect the concatenation of another buffer of bytes.
void CSHA::AddData(char const* pcData, int iDataLength)
{
if(iDataLength < 0)
throw runtime_error(string("FileDigest ERROR: in CSHA::AddData(), Data Length should be >= 0!"));
unsigned int uiT;
switch(m_iMethod)
{
case SHA160:
case SHA256:
{
//Update bitcount
uiT = m_auiBits[0];
if((m_auiBits[0] = uiT + ((unsigned int)iDataLength << 3)) < uiT)
m_auiBits[1]++; //Carry from low to high
m_auiBits[1] += iDataLength >> 29;
uiT = (uiT >> 3) & (BLOCKSIZE-1); //Bytes already
//Handle any leading odd-sized chunks
if(uiT != 0)
{
unsigned char* puc = (unsigned char*)m_aucIn + uiT;
uiT = BLOCKSIZE - uiT;
if(iDataLength < uiT)
{
memcpy(puc, pcData, iDataLength);
return;
}
memcpy(puc, pcData, uiT);
Transform();
pcData += uiT;
iDataLength -= uiT;
}
//Process data in 64-byte chunks
while(iDataLength >= BLOCKSIZE)
{
memcpy(m_aucIn, pcData, BLOCKSIZE);
Transform();
pcData += BLOCKSIZE;
iDataLength -= BLOCKSIZE;
}
//Handle any remaining bytes of data
memcpy(m_aucIn, pcData, iDataLength);
}
break;
case SHA384:
case SHA512:
{
uiT = m_aoui64Bits[0].m_uiRight;
unsigned int uiU = m_aoui64Bits[0].m_uiLeft;
if((m_aoui64Bits[0].m_uiRight = uiT + ((unsigned int)iDataLength << 3)) < uiT)
m_aoui64Bits[0].m_uiLeft++; //Carry from low to high
unsigned int uiV = m_aoui64Bits[1].m_uiRight;
if((m_aoui64Bits[0].m_uiLeft += iDataLength >> 29) < uiU)
m_aoui64Bits[1].m_uiRight++;
if(m_aoui64Bits[1].m_uiRight < uiV)
m_aoui64Bits[1].m_uiLeft++;
uiT = (uiT >> 3) & (BLOCKSIZE2-1); //Bytes already
//Handle any leading odd-sized chunks
if(uiT != 0)
{
unsigned char* puc = (unsigned char*)m_aucIn + uiT;
uiT = BLOCKSIZE2 - uiT;
if(iDataLength < uiT)
{
memcpy(puc, pcData, iDataLength);
return;
}
memcpy(puc, pcData, uiT);
Transform();
pcData += uiT;
iDataLength -= uiT;
}
//Process data in 64-byte chunks
while(iDataLength >= BLOCKSIZE2)
{
memcpy(m_aucIn, pcData, BLOCKSIZE2);
Transform();
pcData += BLOCKSIZE2;
iDataLength -= BLOCKSIZE2;
}
//Handle any remaining bytes of data
memcpy(m_aucIn, pcData, iDataLength);
}
break;
}
//Set the flag
m_bAddData = true;
}
//Final wrapup - pad to 64-byte boundary with the bit pattern
//1 0*(64-bit count of bits processed, MSB-first)
void CSHA::FinalDigest(char* pcDigest)
{
//Is the User's responsability to ensure that pcDigest is properly allocated 20, 32,
//48 or 64 bytes, depending on the method
if(false == m_bAddData)
throw runtime_error(string("FileDigest ERROR: in CSHA::FinalDigest(), No data Added before call!"));
switch(m_iMethod)
{
case SHA160:
case SHA256:
{
unsigned int uiCount;
unsigned char *puc;
//Compute number of bytes mod 64
uiCount = (m_auiBits[0] >> 3) & (BLOCKSIZE-1);
//Set the first char of padding to 0x80. This is safe since there is
//always at least one byte free
puc = m_aucIn + uiCount;
*puc++ = 0x80;
//Bytes of padding needed to make 64 bytes
uiCount = BLOCKSIZE - uiCount - 1;
//Pad out to 56 mod 64
if(uiCount < 8)
{
//Two lots of padding: Pad the first block to 64 bytes
memset(puc, 0, uiCount);
Transform();
//Now fill the next block with 56 bytes
memset(m_aucIn, 0, BLOCKSIZE-8);
}
else
{
//Pad block to 56 bytes
memset(puc, 0, uiCount - 8);
}
//Append length in bits and transform
Word2Bytes(m_auiBits[1], &m_aucIn[BLOCKSIZE-8]);
Word2Bytes(m_auiBits[0], &m_aucIn[BLOCKSIZE-4]);
Transform();
switch(m_iMethod)
{
case SHA160:
{
for(int i=0; i<SHA160LENGTH; i++,pcDigest+=4)
Word2Bytes(m_auiBuf[i], reinterpret_cast<unsigned char*>(pcDigest));
}
break;
case SHA256:
{
for(int i=0; i<SHA256LENGTH; i++,pcDigest+=4)
Word2Bytes(m_auiBuf[i], reinterpret_cast<unsigned char*>(pcDigest));
}
break;
}
}
break;
case SHA384:
case SHA512:
{
unsigned char *puc;
//Compute number of bytes mod 128
unsigned int uiCount = (m_aoui64Bits[0].m_uiRight >> 3) & (BLOCKSIZE2-1);
//Set the first char of padding to 0x80. This is safe since there is
//always at least one byte free
puc = m_aucIn + uiCount;
*puc++ = 0x80;
//Bytes of padding needed to make 128 bytes
uiCount = BLOCKSIZE2 - uiCount - 1;
//Pad out to 112 mod 128
if(uiCount < 16)
{
//Two lots of padding: Pad the first block to 128 bytes
memset(puc, 0, uiCount);
Transform();
//Now fill the next block with 112 bytes
memset(m_aucIn, 0, BLOCKSIZE2-16);
}
else
{
//Pad block to 112 bytes
memset(puc, 0, uiCount - 16);
}
//Append length in bits and transform
Word2Bytes(m_aoui64Bits[1], &m_aucIn[BLOCKSIZE2-16]);
Word2Bytes(m_aoui64Bits[0], &m_aucIn[BLOCKSIZE2-8]);
Transform();
switch(m_iMethod)
{
case SHA384:
{
for(int i=0; i<SHA384LENGTH; i++,pcDigest+=8)
Word2Bytes(m_aoui64Buf[i], reinterpret_cast<unsigned char*>(pcDigest));
}
break;
case SHA512:
{
for(int i=0; i<SHA512LENGTH; i++,pcDigest+=8)
Word2Bytes(m_aoui64Buf[i], reinterpret_cast<unsigned char*>(pcDigest));
}
break;
}
}
break;
}
//Reinitialize
Reset();
}
//Reset current operation in order to prepare a new one
void CSHA::Reset()
{
//Reinitialize
switch(m_iMethod)
{
case SHA160:
{
for(int i=0; i<SHA160LENGTH; i++)
m_auiBuf[i] = sm_H160[i];
m_auiBits[0] = 0;
m_auiBits[1] = 0;
}
break;
case SHA256:
{
for(int i=0; i<SHA256LENGTH; i++)
m_auiBuf[i] = sm_H256[i];
m_auiBits[0] = 0;
m_auiBits[1] = 0;
}
break;
case SHA384:
{
for(int i=0; i<SHA512LENGTH; i++)
m_aoui64Buf[i] = sm_H384[i];
m_aoui64Bits[0].m_uiLeft = 0;
m_aoui64Bits[0].m_uiRight = 0;
m_aoui64Bits[1].m_uiLeft = 0;
m_aoui64Bits[1].m_uiRight = 0;
}
break;
case SHA512:
{
for(int i=0; i<SHA512LENGTH; i++)
m_aoui64Buf[i] = sm_H512[i];
m_aoui64Bits[0].m_uiLeft = 0;
m_aoui64Bits[0].m_uiRight = 0;
m_aoui64Bits[1].m_uiLeft = 0;
m_aoui64Bits[1].m_uiRight = 0;
}
}
//Reset the flag
m_bAddData = false;
}
//The core of the SHA algorithm, this alters an existing SHA hash to
//reflect the addition of 16 longwords of new data.
void CSHA::Transform()
{
switch(m_iMethod)
{
case SHA160:
{
//Expansion of m_aucIn
unsigned char* pucIn = m_aucIn;
unsigned int auiW[80];
int i;
for(i=0; i<16; i++,pucIn+=4)
Bytes2Word(pucIn, auiW[i]);
for(i=16; i<80; i++)
auiW[i] = CircularShift(1, auiW[i-3]^auiW[i-8]^auiW[i-14]^auiW[i-16]);
unsigned int temp;
unsigned int A, B, C, D, E;
A = m_auiBuf[0];
B = m_auiBuf[1];
C = m_auiBuf[2];
D = m_auiBuf[3];
E = m_auiBuf[4];
for(i=0; i<20; i++)
{
temp = CircularShift(5, A) + ((B & C) | ((~B) & D)) + E + auiW[i] + sm_K160[0];
E = D;
D = C;
C = CircularShift(30, B);
B = A;
A = temp;
}
for(i=20; i<40; i++)
{
temp = CircularShift(5, A) + (B ^ C ^ D) + E + auiW[i] + sm_K160[1];
E = D;
D = C;
C = CircularShift(30, B);
B = A;
A = temp;
}
for(i=40; i<60; i++)
{
temp = CircularShift(5, A) + ((B & C) | (B & D) | (C & D)) + E + auiW[i] + sm_K160[2];
E = D;
D = C;
C = CircularShift(30, B);
B = A;
A = temp;
}
for(i=60; i<80; i++)
{
temp = CircularShift(5, A) + (B ^ C ^ D) + E + auiW[i] + sm_K160[3];
E = D;
D = C;
C = CircularShift(30, B);
B = A;
A = temp;
}
m_auiBuf[0] += A;
m_auiBuf[1] += B;
m_auiBuf[2] += C;
m_auiBuf[3] += D;
m_auiBuf[4] += E;
}
break;
case SHA256:
{
//Expansion of m_aucIn
unsigned char* pucIn = m_aucIn;
unsigned int auiW[64];
int i;
for(i=0; i<16; i++,pucIn+=4)
Bytes2Word(pucIn, auiW[i]);
for(i=16; i<64; i++)
auiW[i] = sig1(auiW[i-2]) + auiW[i-7] + sig0(auiW[i-15]) + auiW[i-16];
//OR
//for(i=0; i<48; i++)
// auiW[i+16] = sig1(auiW[i+14]) + auiW[i+9] + sig0(auiW[i+1]) + auiW[i];
unsigned int a, b, c, d, e, f, g, h, t;
a = m_auiBuf[0];
b = m_auiBuf[1];
c = m_auiBuf[2];
d = m_auiBuf[3];
e = m_auiBuf[4];
f = m_auiBuf[5];
g = m_auiBuf[6];
h = m_auiBuf[7];
t = h + SIG1(e) + CH(e, f, g) + sm_K256[0] + auiW[0]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[1] + auiW[1]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[2] + auiW[2]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[3] + auiW[3]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[4] + auiW[4]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[5] + auiW[5]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[6] + auiW[6]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[7] + auiW[7]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[8] + auiW[8]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[9] + auiW[9]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[10] + auiW[10]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[11] + auiW[11]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[12] + auiW[12]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[13] + auiW[13]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[14] + auiW[14]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[15] + auiW[15]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[16] + auiW[16]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[17] + auiW[17]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[18] + auiW[18]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[19] + auiW[19]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[20] + auiW[20]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[21] + auiW[21]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[22] + auiW[22]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[23] + auiW[23]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[24] + auiW[24]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[25] + auiW[25]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[26] + auiW[26]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[27] + auiW[27]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[28] + auiW[28]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[29] + auiW[29]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[30] + auiW[30]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[31] + auiW[31]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[32] + auiW[32]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[33] + auiW[33]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[34] + auiW[34]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[35] + auiW[35]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[36] + auiW[36]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[37] + auiW[37]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[38] + auiW[38]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[39] + auiW[39]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[40] + auiW[40]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[41] + auiW[41]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[42] + auiW[42]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[43] + auiW[43]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[44] + auiW[44]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[45] + auiW[45]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[46] + auiW[46]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[47] + auiW[47]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[48] + auiW[48]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[49] + auiW[49]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[50] + auiW[50]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[51] + auiW[51]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[52] + auiW[52]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[53] + auiW[53]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[54] + auiW[54]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[55] + auiW[55]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K256[56] + auiW[56]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K256[57] + auiW[57]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K256[58] + auiW[58]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K256[59] + auiW[59]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K256[60] + auiW[60]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K256[61] + auiW[61]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K256[62] + auiW[62]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K256[63] + auiW[63]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
//OR
/*
unsigned int a, b, c, d, e, f, g, h, t1, t2;
a = m_auiBuf[0];
b = m_auiBuf[1];
c = m_auiBuf[2];
d = m_auiBuf[3];
e = m_auiBuf[4];
f = m_auiBuf[5];
g = m_auiBuf[6];
h = m_auiBuf[7];
//
for(i=0; i<64; i++)
{
t1 = h + SIG1(e) + CH(e, f, g) + sm_K256[i] + auiW[i];
t2 = SIG0(a) + MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d+t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
*/
m_auiBuf[0] += a;
m_auiBuf[1] += b;
m_auiBuf[2] += c;
m_auiBuf[3] += d;
m_auiBuf[4] += e;
m_auiBuf[5] += f;
m_auiBuf[6] += g;
m_auiBuf[7] += h;
}
break;
case SHA384:
case SHA512:
{
//Expansion of m_aucIn
unsigned char* pucIn = m_aucIn;
SUI64 aoui64W[80];
int i;
for(i=0; i<16; i++,pucIn+=8)
Bytes2Word(pucIn, aoui64W[i]);
for(i=16; i<80; i++)
aoui64W[i] = sig1(aoui64W[i-2]) + aoui64W[i-7] + sig0(aoui64W[i-15]) + aoui64W[i-16];
SUI64 a, b, c, d, e, f, g, h, t;
a = m_aoui64Buf[0];
b = m_aoui64Buf[1];
c = m_aoui64Buf[2];
d = m_aoui64Buf[3];
e = m_aoui64Buf[4];
f = m_aoui64Buf[5];
g = m_aoui64Buf[6];
h = m_aoui64Buf[7];
t = h + SIG1(e) + CH(e, f, g) + sm_K512[0] + aoui64W[0]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[1] + aoui64W[1]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[2] + aoui64W[2]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[3] + aoui64W[3]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[4] + aoui64W[4]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[5] + aoui64W[5]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[6] + aoui64W[6]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[7] + aoui64W[7]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[8] + aoui64W[8]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[9] + aoui64W[9]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[10] + aoui64W[10]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[11] + aoui64W[11]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[12] + aoui64W[12]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[13] + aoui64W[13]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[14] + aoui64W[14]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[15] + aoui64W[15]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[16] + aoui64W[16]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[17] + aoui64W[17]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[18] + aoui64W[18]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[19] + aoui64W[19]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[20] + aoui64W[20]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[21] + aoui64W[21]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[22] + aoui64W[22]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[23] + aoui64W[23]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[24] + aoui64W[24]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[25] + aoui64W[25]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[26] + aoui64W[26]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[27] + aoui64W[27]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[28] + aoui64W[28]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[29] + aoui64W[29]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[30] + aoui64W[30]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[31] + aoui64W[31]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[32] + aoui64W[32]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[33] + aoui64W[33]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[34] + aoui64W[34]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[35] + aoui64W[35]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[36] + aoui64W[36]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[37] + aoui64W[37]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[38] + aoui64W[38]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[39] + aoui64W[39]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[40] + aoui64W[40]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[41] + aoui64W[41]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[42] + aoui64W[42]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[43] + aoui64W[43]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[44] + aoui64W[44]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[45] + aoui64W[45]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[46] + aoui64W[46]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[47] + aoui64W[47]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[48] + aoui64W[48]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[49] + aoui64W[49]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[50] + aoui64W[50]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[51] + aoui64W[51]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[52] + aoui64W[52]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[53] + aoui64W[53]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[54] + aoui64W[54]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[55] + aoui64W[55]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[56] + aoui64W[56]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[57] + aoui64W[57]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[58] + aoui64W[58]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[59] + aoui64W[59]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[60] + aoui64W[60]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[61] + aoui64W[61]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[62] + aoui64W[62]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[63] + aoui64W[63]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[64] + aoui64W[64]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[65] + aoui64W[65]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[66] + aoui64W[66]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[67] + aoui64W[67]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[68] + aoui64W[68]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[69] + aoui64W[69]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[70] + aoui64W[70]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[71] + aoui64W[71]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
t = h + SIG1(e) + CH(e, f, g) + sm_K512[72] + aoui64W[72]; h = t + SIG0(a) + MAJ(a, b, c); d += t;
t = g + SIG1(d) + CH(d, e, f) + sm_K512[73] + aoui64W[73]; g = t + SIG0(h) + MAJ(h, a, b); c += t;
t = f + SIG1(c) + CH(c, d, e) + sm_K512[74] + aoui64W[74]; f = t + SIG0(g) + MAJ(g, h, a); b += t;
t = e + SIG1(b) + CH(b, c, d) + sm_K512[75] + aoui64W[75]; e = t + SIG0(f) + MAJ(f, g, h); a += t;
t = d + SIG1(a) + CH(a, b, c) + sm_K512[76] + aoui64W[76]; d = t + SIG0(e) + MAJ(e, f, g); h += t;
t = c + SIG1(h) + CH(h, a, b) + sm_K512[77] + aoui64W[77]; c = t + SIG0(d) + MAJ(d, e, f); g += t;
t = b + SIG1(g) + CH(g, h, a) + sm_K512[78] + aoui64W[78]; b = t + SIG0(c) + MAJ(c, d, e); f += t;
t = a + SIG1(f) + CH(f, g, h) + sm_K512[79] + aoui64W[79]; a = t + SIG0(b) + MAJ(b, c, d); e += t;
//
m_aoui64Buf[0] += a;
m_aoui64Buf[1] += b;
m_aoui64Buf[2] += c;
m_aoui64Buf[3] += d;
m_aoui64Buf[4] += e;
m_aoui64Buf[5] += f;
m_aoui64Buf[6] += g;
m_aoui64Buf[7] += h;
}
break;
}
}

View File

@@ -1,379 +0,0 @@
//SHA.h
#ifndef __SHA_H__
#define __SHA_H__
#include "MessageDigest.h"
//Typical DISCLAIMER:
//The code in this project is Copyright (C) 2003 by George Anescu. You have the right to
//use and distribute the code in any way you see fit as long as this paragraph is included
//with the distribution. No warranties or claims are made as to the validity of the
//information and code contained herein, so use it at your own risk.
//Structure for representing an Unsigned Integer on 64 bits
struct SUI64
{
//Data
unsigned int m_uiLeft;
unsigned int m_uiRight;
//Operators
SUI64& operator++()
{
unsigned int uiTemp = m_uiRight;
m_uiRight++;
if(m_uiRight < uiTemp)
m_uiLeft++;
return *this;
}
SUI64& operator--()
{
unsigned int uiTemp = m_uiRight;
m_uiRight--;
if(m_uiRight > uiTemp)
m_uiLeft--;
return *this;
}
SUI64& operator+=(SUI64 const& roUI64)
{
m_uiRight += roUI64.m_uiRight;
if(m_uiRight < roUI64.m_uiRight)
m_uiLeft++;
m_uiLeft += roUI64.m_uiLeft;
return *this;
}
SUI64& operator|=(SUI64 const& roUI64)
{
m_uiRight |= roUI64.m_uiRight;
m_uiLeft |= roUI64.m_uiLeft;
return *this;
}
SUI64& operator&=(SUI64 const& roUI64)
{
m_uiRight &= roUI64.m_uiRight;
m_uiLeft &= roUI64.m_uiLeft;
return *this;
}
SUI64& operator^=(SUI64 const& roUI64)
{
m_uiRight ^= roUI64.m_uiRight;
m_uiLeft ^= roUI64.m_uiLeft;
return *this;
}
SUI64& operator<<=(unsigned int uiBits)
{
if(uiBits < 32)
{
(m_uiLeft <<= uiBits) |= (m_uiRight >> (32-uiBits));
m_uiRight <<= uiBits;
}
else
{
m_uiLeft = m_uiRight << (uiBits-32);
m_uiRight = 0;
}
return *this;
}
SUI64& operator>>=(unsigned int uiBits)
{
if(uiBits < 32)
{
(m_uiRight >>= uiBits) |= (m_uiLeft << (32-uiBits));
m_uiLeft >>= uiBits;
}
else
{
m_uiRight = m_uiLeft >> (uiBits-32);
m_uiLeft = 0;
}
return *this;
}
bool operator>(SUI64 const& roUI64) const
{
if(m_uiLeft == roUI64.m_uiLeft)
return m_uiRight > roUI64.m_uiRight;
else
return m_uiLeft > roUI64.m_uiLeft;
}
bool operator<(SUI64 const& roUI64) const
{
if(m_uiLeft == roUI64.m_uiLeft)
return m_uiRight < roUI64.m_uiRight;
else
return m_uiLeft < roUI64.m_uiLeft;
}
};
inline SUI64 operator+(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
SUI64 temp = roUI64_1;
temp += roUI64_2;
return temp;
}
inline SUI64 operator|(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
SUI64 temp = roUI64_1;
temp |= roUI64_2;
return temp;
}
inline SUI64 operator&(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
SUI64 temp = roUI64_1;
temp &= roUI64_2;
return temp;
}
inline SUI64 operator^(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
SUI64 temp = roUI64_1;
temp ^= roUI64_2;
return temp;
}
inline SUI64 operator<<(SUI64 const& roUI64, unsigned int uiBits)
{
SUI64 temp = roUI64;
temp <<= uiBits;
return temp;
}
inline SUI64 operator>>(SUI64 const& roUI64, unsigned int uiBits)
{
SUI64 temp = roUI64;
temp >>= uiBits;
return temp;
}
inline bool operator>(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
return roUI64_1.operator>(roUI64_2);
}
inline bool operator<(SUI64 const& roUI64_1, SUI64 const& roUI64_2)
{
return roUI64_1.operator<(roUI64_2);
}
//SHA Message Digest algorithm
//SHA160 TEST VALUES:
//1)"abc"
//"A9993E364706816ABA3E25717850C26C9CD0D89D"
//
//2)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
//"84983E441C3BD26EBAAE4AA1F95129E5E54670F1"
//
//3)1,000,000 repetitions of "a".
//"34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"
//
//SHA256 TEST VALUES:
//1)One-Block Message "abc"
//"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
//
//2)"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
//"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
//
//3)Multi-Block Message "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
//"CF5B16A778AF8380036CE59E7B0492370B249B11E8F07A51AFAC45037AFEE9D1"
//
//4)Long Message "a" 1,000,000 times
//"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"
//
//SHA384 TEST VALUES:
//1)One-Block Message "abc"
//"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"
//
//2)Multi-Block Message "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
//"09330C33F71147E83D192FC782CD1B4753111B173B3B05D22FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039"
//
//3)Long Message "a" 1,000,000 times
//"9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985"
//
//SHA512 TEST VALUES:
//1)One-Block Message "abc"
//"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a8
//36ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
//
//2)"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
//"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4
//331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"
//
//3)""
//"CF83E1357EEFB8BDF1542850D66D8007D620E4050B5715DC83F4A921D36CE9CE47D0D13C5D85F2B0
//FF8318D2877EEC2F63B931BD47417A81A538327AF927DA3E"
//
//4)Long Message "a" 1,000,000 times
//"E718483D0CE769644E2E42C7BC15B4638E1F98B13B2044285632A803AFA973EBDE0FF244877EA60A
//4CB0432CE577C31BEB009C5C2C49AA2E4EADB217AD8CC09B"
class CSHA : public IMessageDigest
{
public:
enum { SHA160=0, SHA256=1, SHA384=2, SHA512=3 };
//CONSTRUCTOR
CSHA(int iMethod=SHA160);
//Update context to reflect the concatenation of another buffer of bytes.
void AddData(char const* pcData, int iDataLength);
//Final wrapup - pad to 64-byte boundary with the bit pattern
//1 0*(64-bit count of bits processed, MSB-first)
void FinalDigest(char* pcDigest);
//Reset current operation in order to prepare a new one
void Reset();
private:
//Transformation Function
void Transform();
//The Method
int m_iMethod;
enum { BLOCKSIZE2 = BLOCKSIZE<<1 };
//For 32 bits Integers
enum { SHA160LENGTH=5, SHA256LENGTH=8 };
//Context Variables
unsigned int m_auiBuf[SHA256LENGTH]; //Maximum for SHA256
unsigned int m_auiBits[2];
unsigned char m_aucIn[BLOCKSIZE2]; //128 bytes for SHA384, SHA512
//Internal auxiliary static functions
static unsigned int CircularShift(unsigned int uiBits, unsigned int uiWord);
static unsigned int CH(unsigned int x, unsigned int y, unsigned int z);
static unsigned int MAJ(unsigned int x, unsigned int y, unsigned int z);
static unsigned int SIG0(unsigned int x);
static unsigned int SIG1(unsigned int x);
static unsigned int sig0(unsigned int x);
static unsigned int sig1(unsigned int x);
static void Bytes2Word(unsigned char const* pcBytes, unsigned int& ruiWord);
static void Word2Bytes(unsigned int const& ruiWord, unsigned char* pcBytes);
static const unsigned int sm_K160[4];
static const unsigned int sm_H160[SHA160LENGTH];
static const unsigned int sm_K256[64];
static const unsigned int sm_H256[SHA256LENGTH];
//For 64 bits Integers
enum { SHA384LENGTH=6, SHA512LENGTH=8 };
//Context Variables
SUI64 m_aoui64Buf[SHA512LENGTH]; //Maximum for SHA512
SUI64 m_aoui64Bits[2];
//Internal auxiliary static functions
static SUI64 CircularShift(unsigned int uiBits, SUI64 const& roui64Word);
static SUI64 CH(SUI64 const& x, SUI64 const& y, SUI64 const& z);
static SUI64 MAJ(SUI64 const& x, SUI64 const& y, SUI64 const& z);
static SUI64 SIG0(SUI64 const& x);
static SUI64 SIG1(SUI64 const& x);
static SUI64 sig0(SUI64 const& x);
static SUI64 sig1(SUI64 const& x);
static void Bytes2Word(unsigned char const* pcBytes, SUI64& ruiWord);
static void Word2Bytes(SUI64 const& ruiWord, unsigned char* pcBytes);
static const SUI64 sm_H384[SHA512LENGTH]; //Dim is as 512
static const SUI64 sm_K512[80];
static const SUI64 sm_H512[SHA512LENGTH];
};
inline unsigned int CSHA::CircularShift(unsigned int uiBits, unsigned int uiWord)
{
return (uiWord << uiBits) | (uiWord >> (32-uiBits));
}
inline unsigned int CSHA::CH(unsigned int x, unsigned int y, unsigned int z)
{
return ((x&(y^z))^z);
}
inline unsigned int CSHA::MAJ(unsigned int x, unsigned int y, unsigned int z)
{
return (((x|y)&z)|(x&y));
}
inline unsigned int CSHA::SIG0(unsigned int x)
{
return ((x >> 2)|(x << 30)) ^ ((x >> 13)|(x << 19)) ^ ((x >> 22)|(x << 10));
}
inline unsigned int CSHA::SIG1(unsigned int x)
{
return ((x >> 6)|(x << 26)) ^ ((x >> 11)|(x << 21)) ^ ((x >> 25)|(x << 7));
}
inline unsigned int CSHA::sig0(unsigned int x)
{
return ((x >> 7)|(x << 25)) ^ ((x >> 18)|(x << 14)) ^ (x >> 3);
}
inline unsigned int CSHA::sig1(unsigned int x)
{
return ((x >> 17)|(x << 15)) ^ ((x >> 19)|(x << 13)) ^ (x >> 10);
}
inline void CSHA::Bytes2Word(unsigned char const* pcBytes, unsigned int& ruiWord)
{
ruiWord = (unsigned int)*(pcBytes+3) | (unsigned int)(*(pcBytes+2)<<8) |
(unsigned int)(*(pcBytes+1)<<16) | (unsigned int)(*pcBytes<<24);
}
inline void CSHA::Word2Bytes(unsigned int const& ruiWord, unsigned char* pcBytes)
{
pcBytes += 3;
*pcBytes = ruiWord & 0xff;
*--pcBytes = (ruiWord>>8) & 0xff;
*--pcBytes = (ruiWord>>16) & 0xff;
*--pcBytes = (ruiWord>>24) & 0xff;
}
inline SUI64 CSHA::CircularShift(unsigned int uiBits, SUI64 const& roui64Word)
{
return (roui64Word << uiBits) | (roui64Word >> (64-uiBits));
}
inline SUI64 CSHA::CH(SUI64 const& x, SUI64 const& y, SUI64 const& z)
{
return ((x&(y^z))^z);
}
inline SUI64 CSHA::MAJ(SUI64 const& x, SUI64 const& y, SUI64 const& z)
{
return (((x|y)&z)|(x&y));
}
inline SUI64 CSHA::SIG0(SUI64 const& x)
{
return ((x >> 28)|(x << 36)) ^ ((x >> 34)|(x << 30)) ^ ((x >> 39)|(x << 25));
}
inline SUI64 CSHA::SIG1(SUI64 const& x)
{
return ((x >> 14)|(x << 50)) ^ ((x >> 18)|(x << 46)) ^ ((x >> 41)|(x << 23));
}
inline SUI64 CSHA::sig0(SUI64 const& x)
{
return ((x >> 1)|(x << 63)) ^ ((x >> 8)|(x << 56)) ^ (x >> 7);
}
inline SUI64 CSHA::sig1(SUI64 const& x)
{
return ((x >> 19)|(x << 45)) ^ ((x >> 61)|(x << 3)) ^ (x >> 6);
}
inline void CSHA::Bytes2Word(unsigned char const* pcBytes, SUI64& ruiWord)
{
Bytes2Word(pcBytes+4, ruiWord.m_uiRight);
Bytes2Word(pcBytes, ruiWord.m_uiLeft);
}
inline void CSHA::Word2Bytes(SUI64 const& ruiWord, unsigned char* pcBytes)
{
Word2Bytes(ruiWord.m_uiRight, pcBytes+4);
Word2Bytes(ruiWord.m_uiLeft, pcBytes);
}
#endif // __SHA_H__

View File

@@ -1,13 +0,0 @@
#include "multi_emulator.h"
int GenerateSetti(void *pDest)
{
auto pTicket = (int *)pDest;
pTicket[0] = 0xD4CA7F7B;
pTicket[1] = 0xC7DB6023;
pTicket[2] = 0x6D6A2E1F;
pTicket[5] = 0xB4C43105;
return 768;
}

View File

@@ -1,18 +0,0 @@
#include "multi_emulator.h"
int GenerateSteamEmu(void *pDest, int nSteamID)
{
auto pTicket = (int *)pDest;
pTicket[20] = -1; // +80, dproto/reunion wants this value to be -1, but if this value
// does not match -1, then instead of SteamID in [21] cell
// client IP address that xored with 0x25730981 number should
// be used. But dproto/reunion will just skip ticket validation
// in that case.
pTicket[21] = nSteamID; // +84, SteamId, low part. Actually, this is just system volume serial
// number, which comes from GetVolumeInformationA() function. If
// function failed (returned 0), then instead of volume serial number
// 777 number will be written to the ticket.
return 768;
}

View File

@@ -1,12 +0,0 @@
#include "StrUtils.h"
#include <stdlib.h>
void CreateRandomString(char *pszDest, int nLength)
{
static const char c_szAlphaNum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < nLength; ++i)
pszDest[i] = c_szAlphaNum[rand() % (sizeof(c_szAlphaNum) - 1)];
pszDest[nLength] = '\0';
}

View File

@@ -1,3 +0,0 @@
#pragma once
void CreateRandomString(char *pszDest, int nLength);

View File

@@ -1,24 +0,0 @@
#! /usr/bin/env python
# encoding: utf-8
# mittorn, 2018
from waflib import Logs
import os
top = '.'
def options(opt):
return
def configure(conf):
return
def build(bld):
bld.stlib(
source = bld.path.ant_glob(['src/*.cpp']),
target = 'MultiEmulator',
features = 'cxx',
includes = ['include/', 'src/'],
export_includes = ['include/'],
subsystem = bld.env.MSVC_SUBSYSTEM
)

View File

@@ -1 +0,0 @@
#define BZ_VERSION "1.1.0-fwgs"

Submodule 3rdparty/bzip2/bzip2 deleted from 66c46b8c94

View File

@@ -1,34 +0,0 @@
#! /usr/bin/env python
# encoding: utf-8
def options(opt):
pass
def configure(conf):
conf.define('_GNU_SOURCE', 1)
conf.define('BZ_NO_STDIO', 1)
if conf.env.DEST_OS == 'win32':
conf.define('BZ_LCCWIN32', 1)
else:
conf.define('BZ_UNIX', 1)
def build(bld):
# bld(
# features = 'subst',
# source = 'bzip2/bz_version.h.in',
# target = 'bz_version.h',
# BZ_VERSION='1.1.0-fwgs'
# )
bz_sources = ['bzip2/blocksort.c', 'bzip2/huffman.c', 'bzip2/crctable.c', 'bzip2/randtable.c', 'bzip2/compress.c', 'bzip2/decompress.c', 'bzip2/bzlib.c']
bld.stlib(
source = bz_sources,
target = 'bzip2',
# use = 'bz_version.h',
features = 'c',
includes = ['.', 'bzip2/'],
subsystem = bld.env.MSVC_SUBSYSTEM,
export_includes = ['bzip2/']
)

View File

@@ -1,17 +1,17 @@
# Bug-compatibility in Xash3D FWGS
Xash3D FWGS has special mode for games that rely on original engine bugs. In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
Xash3D FWGS has special mode for games that rely on original engine bugs.
In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
At this time, we only have implemented GoldSrc bug-compatibility. It can be enabled with `-bugcomp` command line switch.
When `-bugcomp` is specified without argument, it enables everything. This behavior might be changed or removed in future versions.
When `-bugcomp` is specified with argument, it interpreted as flags separated with `+`. This way it's possible to combine multiple levels of bug-compatibility.
## GoldSrc bug-compatibility
| Flag | Description | Games that require this flag |
| ------- | ----------- | ---------------------------- |
| `peoei` | Reverts `pfnPEntityOfEntIndex` behavior to GoldSrc, where it returns NULL for last player due to incorrect player index comparison | * Counter-Strike: Condition Zero - Deleted Scenes |
| `gsmrf` | Rewrites message at the moment when Game DLL attempts to write an internal engine message, usually specific to GoldSrc protocol. Right now only supports `svc_spawnstaticsound`, more messages added by request. | * MetaMod/AMXModX based mods |
| `sp_attn_none` | Makes sounds with attenuation zero spatialized, i.e. have a stereo effect. | Possibly, every game that was made for GoldSrc. |
### Emulated bugs
* `pfnPEntityOfEntIndex` in GoldSrc returns NULL for last player due to incorrect player index comparison
### Games and mods that require this
* Counter-Strike: Condition Zero - Deleted Scenes

View File

@@ -1,21 +0,0 @@
## Environment variables
#### Xash3D FWGS
The engine respects these environment variables:
| Variable | Type | Description |
| --------------------- | ---------- | ----------- |
| `XASH3D_GAME` | _string_ | Overrides default game directory. Ignored if `-game` command line argument is set |
| `XASH3D_BASEDIR` | _string_ | Sets path to base (root) directory, instead of current working directory |
| `XASH3D_RODIR` | _string_ | Sets path to read-only base (root) directory. Ignored if `-rodir` command line argument is set |
| `XASH3D_EXTRAS_PAK1` | _string_ | Archive file from specified path will be added to virtual filesystem search path in the lowest possible priority |
| `XASH3D_EXTRAS_PAK2` | _string_ | Similar to `XASH3D_EXTRAS_PAK1` but next to it in priority list |
Environment variables NOT listed in the table above are used internally, and aren't considered as stable interface.
#### mdldec
| Variable | Type | Description |
| --------------------- | ---------- | ----------- |
| `MDLDEC_ACT_PATH` | _string_ | If set, will read activities list from this path |

View File

@@ -78,7 +78,6 @@ These strings are specific to Xash3D FWGS.
| `internal_vgui_support` | boolean | 0 | Only for programmers! Required to be set as 1 for PrimeXT!<br>When set to 1, the engine will not load vgui_support DLL, as VGUI support is done (or intentionally ignored) on the game side. |
| `render_picbutton_text` | boolean | 0 | When set to 1, the UI will not use prerendered `btns_main.bmp` and dynamically render them instead |
| `quicksave_aged_count` | integer | 2 | Quick saves limit used in saves rotation |
| `demomap` | string | Empty string | The name of the demo chapter map (Half-Life Uplink) |
## Note on GoldSrc liblist.gam support

View File

@@ -1,14 +0,0 @@
# Support for GoldSrc network protocol
This feature is still work-in-progress, but for now it's available for all users, and we appreciate any bug-reports and contributions around it.
For connecting to GoldSrc-based servers, use this command:
```
connect ip:port gs
```
But keep in mind, there are requirement for server to be able to accept connections from Xash3D-based clients: it should accept HLTV connections.
Without this requirement, you will just get "Steam validation rejected" error on connecting.
That is because proper authorization with Steam API is not implemented in engine yet (but we have plans on it).
In case of ReHLDS with Reunion plugin, by default it rejects HLTV clients. But connections from HLTV can be easily enabled in `reunion.cfg` file.

View File

@@ -1,40 +0,0 @@
### HD (external) textures support
Xash3D supports loading texture replacements in TGA format for almost all types of models in the game, except alias models at this time.
Textures are expected to be located at:
* `modfolder/materials/<mapname>` - for a specific map
* `modfolder/materials/common` - common for all maps
* `modfolder/materials/decals` - for decals
* `modfolder/materials/models/<model>` - for models (texture name must match the internal texture name in the model)
Support for high-resolution textures is enabled setting `host_allow_materials` cvar to `1` or in the menu, in "Video options" section.
#### Xash3D FWGS additions
In addition to paths above, Xash3D FWGS checks following paths:
* `modfolder/materials/sprites/<sprite>` - for sprites, except HUD sprites
Also, to check which texture replacements are loaded successfully, failed or weren't found, a mod developer can set `host_allow_materials` cvar value to `2`. The engine will spew log at any developer level in the following format:
```
Looking for <replacement> replacement... <status code> (<path relative to mod directory>)
```
Status codes:
* `OK` - texture replacement file was found and loaded into GPU memory successfully
* `FAIL` - texture file was found but hasn't been parsed or loaded successfully. Refer to engine log for more details.
* `MISS` - texture file wasn't found
Example:
```
Looking for maps/bounce.bsp:!waterblue tex replacement...OK (materials/common/!waterblue.tga)
Looking for maps/bounce.bsp:!waterblue_luma tex replacement...MISS (not found)
Looking for {shot2 decal replacement...MISS (materials/decals/{shot2.tga)
Looking for {shot4 decal replacement...MISS (materials/decals/{shot4.tga)
Looking for {shot3 decal replacement...MISS (materials/decals/{shot3.tga)
Looking for models/gman tex replacement...FAIL (materials/models/gman/GMan_Case1.tga)
Looking for models/gman tex replacement...FAIL (materials/models/gman/inside_1.tga)
```

View File

@@ -19,22 +19,7 @@
- [List of XashXT-based mods](#list-of-xashxt-based-mods)
- [List of maps for They Hunger](#list-of-maps-for-they-hunger)
- [List of games and mods with custom gamedll](#list-of-games-and-mods-with-custom-gamedll)
- [List of mods for Counter Strike](#list-of-mods-for-counter-strike)
- [List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS](#list-of-supported-mods-from-mobile_hacks-branch-of-hlsdk-portable-by-fwgs)
# List of supported mods from mobile_hacks branch of HLSDK Portable by FWGS
1. [Afraid of Monsters](https://www.moddb.com/mods/afraid-of-monsters/downloads/afraid-of-monsters-v1)
2. [Big Lolly](https://www.moddb.com/mods/big-lolly)
3. [Half-Life: Blue Shift](https://store.steampowered.com/app/130/HalfLife_Blue_Shift/)
4. [Half-Secret](https://www.moddb.com/mods/half-secret)
5. [Case Closed](https://www.moddb.com/mods/caseclosed)
6. [Bloody Pizza - Vendetta](https://www.moddb.com/games/half-life/addons/bloody-pizza-vendetta)
7. [Borderlands](https://www.moddb.com/games/half-life/addons/borderlands-v04)
8. [Half-Life: Induction](https://www.moddb.com/mods/half-life-induction/downloads/half-life-induction-12)
9. [Redemption/Absolute Redemption](https://www.moddb.com/mods/absolute-redemption)
10. [Sewer beta](https://www.moddb.com/games/half-life/addons/sewer-beta)
11. [Times of Troubles](https://www.moddb.com/mods/times-of-troubles)
12. [Half-Life: Urbicide](https://www.moddb.com/mods/half-life-urbicide)
- [List of mods for Counter Strike(Android only)](#list-of-mods-for-counter-strike)
# List of Half-Life-based mods
Originally this list was written by *Qwertyus*(*Qortez*)
@@ -191,7 +176,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
143. [Operation: Nova](http://www.moddb.com/mods/half-life-operation-nova) (there is an inner bug with an M60 machinegun on a map with Osprey: it can be activated and used if you are staying in front of it, not behind it)
144. [Optimum Fear](https://www.fileplanet.com/7472/0/fileinfo/Optimum-Fear)
145. [Outrun](http://www.moddb.com/mods/outrun)
146. [Outwards (Day One)](https://web.archive.org/web/20161026104825/http://visgi.info/maps/)
146. [Outwards (Day One)](https://drive.google.com/file/d/1mjQ8wUazYbwTq9Ocg0Vs0raq4avbTRne/view?usp=sharing)
147. [Overhaul Pack](http://www.moddb.com/mods/half-life-overhaul-pack) (Just HD pack for Half-Life)
148. [P.I.Z.D.E.C.](https://www.runthinkshootlive.com/posts/pizdec/)
149. [pagoda](http://www.moddb.com/mods/pagoda1)
@@ -297,7 +282,7 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
6. [Catacombs: Part 1](https://www.runthinkshootlive.com/posts/catacombs/)
7. [Cro-man's Office Mappack](http://twhl.info/vault.php?map=5547)
8. [Half-Life Episode Two Demo Alpha v1.0](http://hl.loess.ru/?mod=451)
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
9. [Hazardous-Course (first version of Hazardous-Course 2)](https://drive.google.com/file/d/16djJZSpNWKyScSxSyMqX-u_S-2i400rl/view?usp=sharing)
10. [High Tech v0.2](http://hl.loess.ru/?mod=499)
11. [HL Shadows, Part 1](https://www.fileplanet.com/7466/0/fileinfo/'HL-Shadows',-Part-1)
12. [HLNewEnd](http://twhl.info/vault.php?map=2275)
@@ -320,11 +305,11 @@ For mappacks - place *.bsp files to **valve/maps** folder, *.wad files to **valv
29. [Shortcut v1.0 Beta](https://www.runthinkshootlive.com/posts/shortcut/)
30. [Stoka](https://www.ceskemody.cz/mapy.php?lng=1&clanek=222&razeni_hra=1&pn=stoka)
31. [Striker's Compo 26](http://twhl.info/vault.php?map=5190) (buggy)
32. [Technology Test 2](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
32. [Technology Test 2](https://drive.google.com/file/d/1LfldzsMIN5j07bgtNkfY5v0Xl0S9de_G/view?usp=sharing)
33. [The Gate Playable Demo](https://www.fileplanet.com/116347/110000/fileinfo/The-Gate-Playable-Demo)
34. [They are Back](https://www.runthinkshootlive.com/posts/they-are-back/)
35. [Tiefseelabor( Deep Sea Laboratory )](https://www.runthinkshootlive.com/posts/deep-sea-laboratory/)
36. [Time-Shift](https://web.archive.org/web/20110512012317/http://www.richmans-maps.ch.vu/)
36. [Time-Shift](https://drive.google.com/file/d/1pK1s-2SIlSMQHVRPMLdC_94wTa__8_DX/view?usp=sharing)
37. [Train Single Beta](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (Remove **gfx.wad** from **TrainSingle** folder)
38. [WAR: The Killer Beta 0.1](http://www.moddb.com/mods/war)
39. [White Force Beta( Residual Point prototype )](http://www.moddb.com/mods/hl-residual-point/downloads/white-force-beta-2002)
@@ -394,7 +379,7 @@ Mods:
5. [Half-Life Baby v1.4](http://www.moddb.com/games/half-life/addons/half-life-baby) (it's an unfinished but playable mod; after installing of the mod open **liblist.gam** or **gameinfo.txt** file in the mod's folder and correct the line **gamedll "..\hlbaby\dlls\hl.dll"** for **gamedll "dlls\hl.dll"**, otherwise you'll not be able to start a game)
6. [Half-Secret](http://www.moddb.com/mods/half-secret) (this mod has custom **weapon_snark** code)
7. [Induction](http://www.moddb.com/mods/half-life-induction) (this mod has new item - **item_flashlight**)
8. [Lost in Black Mesa(first version without HLFX)](https://web.archive.org/web/20160407041812/http://half-life.ru/forum/showthread.php?threadid=13959) (download links dead!)
8. [Lost in Black Mesa(first version without HLFX)](https://drive.google.com/file/d/1bEnm_AxJs-ly8hTEZIQBw_v2BsXdSiGa/view?usp=sharing)
9. [Soldier](http://www.moddb.com/mods/half-life-soldier)
10. [Solo Operations](http://www.moddb.com/mods/solo-operations)
11. [The Blood v1.1](http://hl.loess.ru/?mods=&search=The+Blood) (there are some inner bugs in the mod, but they don't interfere with a game progress)
@@ -455,7 +440,7 @@ Mods:
51. [Data-base](https://www.runthinkshootlive.com/posts/database/)
52. [de_dust2_azabetfeN](https://cs-mapping.com.ua/forum/showthread.php?t=36394) (remove **cl_dlls** & **dlls** folders from inside of mod's directory before you start the game)
53. [De-railed](http://twhl.info/competitions.php?results=7)
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://web.archive.org/web/20151030005310/http://www.gamefront.com/files/13532512)
54. [Dead Shift Beta](http://www.moddb.com/mods/dead-shift) - [Demo 1](https://www.gamewatcher.com/mods/half-life-mod/dead-shift-1-0-beta) & [Demo 2](https://drive.google.com/file/d/1uHvr8xONogTTNOy-8X6G4ehFV6Eawvbq/view?usp=sharing)
55. [Deep](http://twhl.info/vault.php?map=1669)
56. [Desert Attack](http://fyzzer.narod.ru/index.html)
57. [Desert Combat Demo](https://www.fileplanet.com/190487/190000/fileinfo/Half-Life---Desert-Combat-Mod) (despite a big file size there's only one small unfinished map)
@@ -513,8 +498,8 @@ Mods:
109. [Hospital](https://gamebanana.com/maps/167446) (you need to edit **liblist.gam** file in the mod's folder - delete *gamedll & type* strings from it before you start to play)
110. [Hostage](https://www.runthinkshootlive.com/posts/hostage-2/)
111. [House](http://www.artpeter.net/Data/HalfLife/Hl.php)
112. [Impulse 101 Fun - The Train](http://web.archive.org/web/20070305075816/http://www.twhl.co.za/mapvault/2817.zip) (map from *TWHL* by *Archie* aka *The Hunter*)
113. [In America](https://web.archive.org/web/20170221213409/http://www.lambda-force.org/load/half_life/karty/half_life_in_america/18-1-0-476)
112. [Impulse 101 Fun - The Train](https://drive.google.com/file/d/1jAuMCCmREH0mfAEAscqaG8FQGa2uNknb/view?usp=sharing) (map from *TWHL* by *Archie* aka *The Hunter*)
113. [In America](https://drive.google.com/file/d/1gOC8zfnUvBxRy8Rr8juNiUNbLYjoZpnn/view?usp=sharing)
114. [In the Kitchen](http://twhl.info/vault.php?map=4314)
115. [Infiltration](https://www.fileplanet.com/7467/0/fileinfo/Infiltration)
116. [Interactivity & Lots of Entities](http://twhl.info/vault.php?map=5744) (link dead!)

View File

@@ -2,7 +2,7 @@
[![builds.sr.ht status](https://builds.sr.ht/~a1batross/xash3d-fwgs.svg)](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [![GitHub Actions Status](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [![Discord Server](https://img.shields.io/discord/355697768582610945.svg)](http://fwgsdiscord.mentality.rip/) \
[![Download Stable](https://img.shields.io/badge/download-stable-yellow)](https://github.com/FWGS/xash3d-fwgs/releases/latest) [![Download Testing](https://img.shields.io/badge/downloads-testing-orange)](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
Xash3D (pronounced `[ksɑʂ]`) FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
Xash3D FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
@@ -11,12 +11,12 @@ Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://ww
If you like Xash3D FWGS, consider supporting individual engine maintainers. By supporting us, you help to continue developing this game engine further. The sponsorship links are available in [documentation](Documentation/donate.md).
## Fork features
* Steam Half-Life (HLSDK 2.5) support.
* Steam Half-Life (HLSDK 2.4) support.
* Crossplatform and modern compilers support: supports Windows, Linux, BSD & Android on x86 & ARM and [many more](Documentation/ports.md).
* Better multiplayer: multiple master servers, headless dedicated server, voice chat, [GoldSrc protocol support](Documentation/goldsrc-protocol-support.md) and IPv6 support.
* Better multiplayer support: multiple master servers, headless dedicated server, voice chat and IPv6 support.
* Multiple renderers support: OpenGL, GLESv1, GLESv2 and Software.
* Advanced virtual filesystem: `.pk3` and `.pk3dir` support, compatibility with GoldSrc FS module, fast case-insensitivity emulation for crossplatform.
* Mobility API: better game integration on mobile devices (vibration, touch controls).
* Mobility API: better game integration on mobile devices (vibration, touch controls)
* Different input methods: touch and gamepad in addition to mouse & keyboard.
* TrueType font rendering, as a part of mainui_cpp.
* External VGUI support module.
@@ -28,28 +28,29 @@ If you like Xash3D FWGS, consider supporting individual engine maintainers. By s
1) Copy engine binaries to some directory.
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
You still needed to copy `valve` directory as all game resources located there.
3) Run the main executable (`xash3d.exe` or AppImage).
For additional info, run Xash3D with `-help` command line key.
## Contributing
* Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html.
* Issues are accepted in both English and Russian.
* Before sending an issue, check if someone already reported your issue. Make sure you're following "How To Ask Questions The Smart Way" guide by Eric Steven Raymond. Read more: http://www.catb.org/~esr/faqs/smart-questions.html
* Issues are accepted in both English and Russian
* Before sending a PR, check if you followed our contribution guide in CONTRIBUTING.md file.
## Build instructions
We are using Waf build system. If you have some Waf-related questions, I recommend you to read [Waf Book](https://waf.io/book/).
We are using Waf build system. If you have some Waf-related questions, I recommend you to read https://waf.io/book/
NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependencies we're using!
### Prerequisites
If your CPU is x86 compatible and you're on Windows or Linux, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
If your CPU is x86 compatible, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
This repository contains our fork of HLSDK and restored source code for Half-Life expansions and some mods.
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
#### Windows (Visual Studio)
* Install Visual Studio.
@@ -61,39 +62,31 @@ This repository contains our fork of HLSDK and restored source code for Half-Lif
#### GNU/Linux
##### Debian/Ubuntu
* For 32-bit engine on 64-bit x86 operating system:
* Enable i386 on your system: `$ sudo dpkg --add-architecture i386`.
* Install development tools: `$ sudo apt install build-essential gcc-multilib g++-multilib python libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype6-dev:i386 libopus-dev:i386 libbz2-dev:i386`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig`.
* Enable i386 on your system, if you're compiling 32-bit engine on amd64. If not, skip this
* For non-x86 systems:
* Install development tools: `$ sudo apt install build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev libopus-dev libbz2-dev`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
##### RedHat/Fedora
* For 32-bit engine on 64-bit x86 operating system:
* Install development tools: `$ sudo dnf install gcc gcc-c++ glibc-devel.i686 SDL2-devel.i686 opus-devel.i686 fontconfig-devel.i686 freetype-devel.i686 bzip2-devel.i686`.
* Set PKG_CONFIG_PATH environment variable to point at 32-bit libraries: `$ export PKG_CONFIG_PATH=/usr/lib/pkgconfig`.
* For non-x86 systems:
* Install development tools: `$ sudo dnf install gcc gcc-c++ SDL2-devel opus-devel fontconfig-devel freetype-devel bzip2-devel`.
* Clone this repostory: `$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`.
`$ sudo dpkg --add-architecture i386`
* Install development tools
* For 32-bit engine on amd64: \
`$ sudo apt install build-essential gcc-multilib g++-multilib python libsdl2-dev:i386 libfontconfig-dev:i386 libfreetype6-dev:i386`
* For everything else: \
`$ sudo apt install build-essential python libsdl2-dev libfontconfig-dev libfreetype6-dev`
* Clone this repostory:
`$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`
### Building
#### Windows (Visual Studio)
0) Open command line.
0) Open command line
1) Navigate to `xash3d-fwgs` directory.
2) (optional) Examine which build options are available: `waf --help`.
3) Configure build: `waf configure --sdl2=c:/path/to/SDL2`.
4) Compile: `waf build`.
5) Install: `waf install --destdir=c:/path/to/any/output/directory`.
2) Carefully examine which build options are available: `waf --help`
3) Configure build: `waf configure -T release --sdl2=c:/path/to/SDL2`
4) Compile: `waf build`
5) Install: `waf install --destdir=c:/path/to/any/output/directory`
#### Linux
If compiling 32-bit on amd64, make sure `PKG_CONFIG_PATH` from the previous step is set correctly, prior to running configure.
If compiling 32-bit on amd64, you may need to supply `export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig` prior to running configure.
0) (optional) Examine which build options are available: `./waf --help`.
1) Configure build: `./waf configure` (you need to pass `-8` to compile 64-bit engine on 64-bit x86 processor).
2) Compile: `./waf build`.
3) Install: `./waf install --destdir=/path/to/any/output/directory`.
0) Examine which build options are available: `./waf --help`
1) Configure build: `./waf configure -T release`
(You need to pass `-8` to compile 64-bit engine on 64-bit x86 processor)
2) Compile: `./waf build`
3) Install(optional): `./waf install --destdir=/path/to/any/output/directory`

25
common/boneinfo.h Normal file
View File

@@ -0,0 +1,25 @@
/*
boneinfo.h - structure that send delta-compressed bones across network
Copyright (C) 2018 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#ifndef BONEINFO_H
#define BONEINFO_H
typedef struct
{
vec3_t angles;
vec3_t origin;
} boneinfo_t;
#endif//BONEINFO_H

View File

@@ -54,6 +54,7 @@ BRUSH MODELS
#define SURF_CONVEYOR BIT( 6 ) // scrolled texture (was SURF_DRAWBACKGROUND)
#define SURF_UNDERWATER BIT( 7 ) // caustics
#define SURF_TRANSPARENT BIT( 8 ) // it's a transparent texture (was SURF_DONTWARP)
#define SURF_REFLECT BIT( 31 ) // mirrors
// lightstyle management
#define LM_STYLES 4 // MAXLIGHTMAPS

View File

@@ -127,23 +127,14 @@ typedef struct
int flags; // sky or slime, no lightmap or 256 subdivision
} mtexinfo_t;
// a1ba: changed size to avoid undefined behavior. Check your allocations if you take this header!
// For example:
// before: malloc( sizeof( glpoly_t ) + ( numverts - 4 ) * VERTEXSIZE * sizeof( float ))
// after (C): malloc( sizeof( glpoly_t ) + numverts * VERTEXSIZE * sizeof( float ))
// after (C++): malloc( sizeof( glpoly_t ) + ( numverts - 1 ) * VERTEXSIZE * sizeof( float ))
typedef struct glpoly2_s
typedef struct glpoly_s
{
struct glpoly2_s *next;
struct glpoly2_s *chain;
struct glpoly_s *next;
struct glpoly_s *chain;
int numverts;
int flags; // for SURF_UNDERWATER
#ifdef __cplusplus
float verts[1][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
#else
float verts[][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
#endif
} glpoly2_t;
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
} glpoly_t;
typedef struct mnode_s
{
@@ -182,7 +173,7 @@ struct decal_s
short entityIndex; // Entity this is attached to
// Xash3D specific
vec3_t position; // location of the decal center in world space.
glpoly2_t *polys; // precomputed decal vertices
glpoly_t *polys; // precomputed decal vertices
intptr_t reserved[4]; // just for future expansions or mod-makers
};
@@ -237,7 +228,9 @@ typedef struct mextrasurf_s
unsigned short numverts; // world->vertexes[]
int firstvertex; // fisrt look up in tr.tbn_vectors[], then acess to world->vertexes[]
intptr_t reserved[32]; // just for future expansions or mod-makers
struct mextrasurf_s *mirrorchain; // engine-side mirrors, may be ignored in mods with custom renderers
intptr_t reserved[31]; // just for future expansions or mod-makers
} mextrasurf_t;
struct msurface_s
@@ -255,7 +248,7 @@ struct msurface_s
int light_s, light_t; // gl lightmap coordinates
glpoly2_t *polys; // multiple if warped
glpoly_t *polys; // multiple if warped
struct msurface_s *texturechain;
mtexinfo_t *texinfo;
@@ -497,8 +490,7 @@ typedef struct
int flags;
float size;
const trivertex_t **pposeverts; // only valid during loading, used to build GL mesh
intptr_t reserved[7]; // VBO offsets
int reserved[8]; // VBO offsets
int numposes;
int poseverts;
@@ -541,10 +533,17 @@ typedef struct
#define MAX_MOVIES 8
#define MAX_CDTRACKS 32
#define MAX_CLIENT_SPRITES 512 // SpriteTextures (0-256 hud, 256-512 client)
#define MAX_EFRAGS 8192 // Arcane Dimensions required
#define MAX_REQUESTS 64
STATIC_CHECK_SIZEOF( mextrasurf_t, 324, 496 );
STATIC_CHECK_SIZEOF( decal_t, 60, 88 );
STATIC_CHECK_SIZEOF( mfaceinfo_t, 176, 304 );
#if ! XASH_64BIT
STATIC_ASSERT( sizeof( mextrasurf_t ) == 324, "mextrasurf_t unexpected size" );
STATIC_ASSERT( sizeof( decal_t ) == 60, "decal_t unexpected size");
STATIC_ASSERT( sizeof( mfaceinfo_t ) == 176, "mfaceinfo_t unexpected size");
#else
STATIC_ASSERT( sizeof( mextrasurf_t) == 496, "mextrasurf_t unexpected size");
STATIC_ASSERT( sizeof( decal_t ) == 88, "decal_t unexpected size");
STATIC_ASSERT( sizeof( mfaceinfo_t ) == 304, "mfaceinfo_t unexpected size");
#endif
#endif//COM_MODEL_H

View File

@@ -92,6 +92,7 @@
#define SOLID_BSP 4 // bsp clip, touch on edge, block
#define SOLID_CUSTOM 5 // call external callbacks for tracing
#define SOLID_PORTAL 6 // borrowed from FTE
#define SOLID_GIB 7 // do not block, only collide with solid brushes
// edict->deadflag values
#define DEAD_NO 0 // alive
@@ -114,6 +115,8 @@
#define EF_LIGHT 64 // rocket flare glow sprite
#define EF_NODRAW 128 // don't draw entity
#define EF_NOREFLECT (1U<<24) // Entity won't reflecting in mirrors
#define EF_REFLECTONLY (1U<<25) // Entity will be drawing only in mirrors
#define EF_WATERSIDES (1U<<26) // Do not remove sides for func_water entity
#define EF_FULLBRIGHT (1U<<27) // Just get fullbright
#define EF_NOSHADOW (1U<<28) // ignore shadow for this entity

View File

@@ -1,122 +1,49 @@
/*
cvardef.h - quake cvar definition
Copyright (C) 1997-2001 Id Software, Inc.
Copyright (C) 2024 Alibek Omarov
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#ifndef CVARDEF_H
#define CVARDEF_H
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
#define FCVAR_ARCHIVE (1<<0) // set to cause it to be saved to vars.rc
#define FCVAR_USERINFO (1<<1) // changes the client's info string
#define FCVAR_SERVER (1<<2) // notifies players when changed
#define FCVAR_EXTDLL (1<<3) // defined by external DLL
#define FCVAR_CLIENTDLL (1<<4) // defined by the client dll
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
#define FCVAR_PRINTABLEONLY (1<<7) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
#define FCVAR_UNLOGGED (1<<8) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
#define FCVAR_NOEXTRAWHITEPACE (1<<9) // strip trailing/leading white space from this cvar
#define FCVAR_PRIVILEGED (1<<10) // only available in privileged mode
#define FCVAR_FILTERABLE (1<<11) // filtered in unprivileged mode if cl_filterstuffcmd is 1
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// Xash3D extensions
#define FCVAR_GLCONFIG (1<<12) // write it into <renderer>.cfg(see RefAPI)
#define FCVAR_CHANGED (1<<13) // set each time the cvar is changed
#define FCVAR_GAMEUIDLL (1<<14) // defined by the menu DLL
#define FCVAR_CHEAT (1<<15) // can not be changed if cheats are disabled
See the GNU General Public License for more details.
// a1ba: let's reuse higher bits for flags extensions from now on
#define FCVAR_LATCH (1<<30) // notify client what this cvar will be applied only after server restart (but don't does more nothing)
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef CVAR
#define CVAR
#include STDINT_H
#include "xash3d_types.h"
/*
cvar_t variables are used to hold scalar or string variables that can be changed
or displayed at the console or prog code as well as accessed directly
in C code.
The user can access cvars from the console in three ways:
r_draworder prints the current value
r_draworder 0 sets the current value to 0
set r_draworder 0 as above, but creates the cvar if not present
Cvars are restricted from having the same names as commands to keep this
interface from being ambiguous.
The are also occasionally used to communicated information between different
modules of the program.
*/
enum
typedef struct cvar_s
{
// GoldSrc compatibility flags
FCVAR_ARCHIVE = 1 << 0, // set to cause it to be saved to vars.rc
FCVAR_USERINFO = 1 << 1, // added to userinfo when changed
FCVAR_SERVER = 1 << 2, // added to serverinfo when changed, will notify clients by default
FCVAR_EXTDLL = 1 << 3, // defined by server.dll
FCVAR_CLIENTDLL = 1 << 4, // defined by client.dll
FCVAR_PROTECTED = 1 << 5, // private server cvar
FCVAR_SPONLY = 1 << 6, // can be set only in singleplayer
FCVAR_PRINTABLEONLY = 1 << 7, // only allows printable characters
FCVAR_UNLOGGED = 1 << 8, // disables notifying client about server cvar change
FCVAR_NOEXTRAWHITESPACE = 1 << 9, // removes space characters from the beginning and the end of the string
FCVAR_PRIVILEGED = 1 << 10, // only available in privileged mode
FCVAR_FILTERABLE = 1 << 11, // treated as privileged if cl_filterstuffcmd is 1, otherwise ignored
char *name;
char *string;
int flags;
float value;
struct cvar_s *next;
} cvar_t;
// Xash3D public flags
// FCVAR_LATCH = 1 << 11, // deprecated Xash3D flag, conflicts with FCVAR_FILTERABLE. Use another FCVAR_LATCH!
FCVAR_GLCONFIG = 1 << 12, // set to cause it to be saved to <renderer>.cfg (see RefAPI)
FCVAR_CHANGED = 1 << 13, // set each time the cvar changed
FCVAR_GAMEUIDLL = 1 << 14, // defined by menu.dll
FCVAR_CHEAT = 1 << 15, // cannot be changed if sv_cheats is 0
#if REF_DLL || ENGINE_DLL // Xash3D internal flags, MUST NOT be used outside of engine
FCVAR_RENDERINFO = 1 << 16, // set to cause it to be saved to video.cfg
FCVAR_READ_ONLY = 1 << 17, // display only, cannot be set by user at all
FCVAR_EXTENDED = 1 << 18, // extended cvar structure
FCVAR_ALLOCATED = 1 << 19, // allocated by the engine, must be freed with Mem_Free
FCVAR_VIDRESTART = 1 << 20, // triggers video subsystem to recreate/modify window parameters
FCVAR_TEMPORARY = 1 << 21, // only used to temporarly hold some value, can be unlinked
FCVAR_MOVEVARS = 1 << 22, // access to movevars_t structure, synchornized between client and server
FCVAR_USER_CREATED = 1 << 23, // created by a set command
FCVAR_REFDLL = 1 << 29, // (Xash3D FWGS internal flag) defined by the renderer DLL
#endif // REF_DLL || ENGINE_DLL
FCVAR_LATCH = 1 << 30, // (Xash3D FWGS public flag, was FCVAR_FILTERABLE in Xash3D) save changes until server restart
};
struct cvar_s {
char *name;
char *string;
uint32_t flags;
float value;
struct cvar_s *next;
};
typedef struct cvar_s cvar_t;
STATIC_CHECK_SIZEOF( struct cvar_s, 20, 32 );
#if REF_DLL || ENGINE_DLL // Xash3D internal cvar format, MUST NOT be used outside of engine
struct convar_s {
char *name;
char *string;
uint32_t flags;
float value;
struct convar_s *next;
char *desc;
char *def_string;
};
typedef struct convar_s convar_t;
#if XASH_64BIT
#define CVAR_SENTINEL (uintptr_t)0xDEADBEEFDEADBEEF
#else
#define CVAR_SENTINEL (uintptr_t)0xDEADBEEF
#endif
#define CVAR_CHECK_SENTINEL( cv ) ((uintptr_t)(cv)->next == CVAR_SENTINEL)
#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) \
convar_t cv = { (char*)cvname, (char*)cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, (char*)cvdesc, NULL }
#define CVAR_DEFINE_AUTO( cv, cvstr, cvflags, cvdesc ) CVAR_DEFINE( cv, #cv, cvstr, cvflags, cvdesc )
#endif // REF_DLL || ENGINE_DLL
#endif // CVAR
#endif//CVARDEF_H

View File

@@ -164,6 +164,10 @@ Default build-depended cvar and constant values
#define XASH_INTERNAL_GAMELIBS
#endif // XASH_ANDROID || XASH_IOS || XASH_EMSCRIPTEN
#if XASH_ANDROID && XASH_SDL
#define XASH_ANDROID_ASSETS 1
#endif
// Defaults
#ifndef DEFAULT_TOUCH_ENABLE
#define DEFAULT_TOUCH_ENABLE "0"

View File

@@ -1,5 +1,5 @@
/*
enginefeatures.h - engine features that can be enabled by mod-maker request
features.h - engine features that can be enabled by mod-maker request
Copyright (C) 2012 Uncle Mike
This program is free software: you can redistribute it and/or modify
@@ -27,7 +27,7 @@ GNU General Public License for more details.
#define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine
#define ENGINE_LINEAR_GAMMA_SPACE (1<<8) // disable influence of gamma/brightness cvars to textures/lightmaps, for mods with custom renderer
#define ENGINE_DISABLE_HDTEXTURES (1U<<30) // disable support of HD-textures in case custom renderer have separate way to load them
#define ENGINE_ALLOW_MIRRORS (1U<<30) // allow mirrors in engine renderer
#define ENGINE_STEP_POSHISTORY_LERP (1U<<31) // enable MOVETYPE_STEP interpolation based on position history. Incompatible with ENGINE_COMPUTE_STUDIO_LERP!
// adjust the mask when features will be added or removed
@@ -41,6 +41,7 @@ GNU General Public License for more details.
| ENGINE_IMPROVED_LINETRACE \
| ENGINE_COMPUTE_STUDIO_LERP \
| ENGINE_LINEAR_GAMMA_SPACE \
| ENGINE_ALLOW_MIRRORS \
| ENGINE_STEP_POSHISTORY_LERP )
#endif//FEATURES_H

View File

@@ -30,7 +30,7 @@ GAMEINFO stuff
internal shared gameinfo structure (readonly for engine parts)
========================================================================
*/
typedef struct GAMEINFO_s
typedef struct
{
// filesystem info
char gamefolder[64]; // used for change game '-game x'
@@ -50,48 +50,4 @@ typedef struct GAMEINFO_s
int gamemode;
} GAMEINFO;
/*
========================================================================
Extended GameInfo struct introduced in Xash3D FWGS
GAMEINFO can't be reliably extended, as nor engine, nor menu can't be
sure about struct size. By adding struct versioning, we can check the
presense for extra fields.
========================================================================
*/
#define GAMEINFO_VERSION 2
typedef enum gametype_e
{
GAME_NORMAL,
GAME_SINGLEPLAYER_ONLY,
GAME_MULTIPLAYER_ONLY,
} gametype_t;
typedef struct gameinfo2_s
{
int gi_version; // should be set to desired struct version, e.g. GAMEINFO_VERSION
// filesystem info
char gamefolder[64]; // used for change game
char startmap[64]; // map to start singleplayer game from
char trainmap[64]; // map to start hazardous course from (if specified)
char demomap[64]; // map to start demo chapter from (if specified)
char title[64]; // game title
char iconpath[64]; // path to game icon
char version[16]; // game version (optional)
uint32_t flags; // gameinfo flags, extended to fit more flags
// mod info
char game_url[256]; // link to a developer's site
char update_url[256]; // link to updates page
char type[64]; // single, toolkit, multiplayer, etc
char date[64]; // release date
uint64_t size; // size in bytes
gametype_t gamemode;
} gameinfo2_t;
#endif//GAMEINFO_H

View File

@@ -30,6 +30,6 @@ typedef struct
int state; // low bit is down state
} kbutton_t;
STATIC_CHECK_SIZEOF( kbutton_t, 12, 12 );
STATIC_ASSERT( sizeof( kbutton_t ) == 12, "kbutton_t isn't 12 bytes!" );
#endif // KBUTTON_H

View File

@@ -27,7 +27,6 @@
// Set this flag for things like broadcast requests, etc. where the engine should not
// kill the request hook after receiving the first response
#define FNETAPI_MULTIPLE_RESPONSE ( 1<<0 )
#define FNETAPI_LEGACY_PROTOCOL ( 1<<1 ) // xash3d-fwgs extension
struct net_response_s;
typedef void (*net_api_response_func_t) ( struct net_response_s *response );
@@ -36,7 +35,6 @@ typedef void (*net_api_response_func_t) ( struct net_response_s *response );
#define NET_ERROR_TIMEOUT ( 1<<0 )
#define NET_ERROR_PROTO_UNSUPPORTED ( 1<<1 )
#define NET_ERROR_UNDEFINED ( 1<<2 )
#define NET_ERROR_FORBIDDEN ( 1<<3 ) // xash3d-fwgs extension
typedef struct net_adrlist_s
{

View File

@@ -69,6 +69,6 @@ typedef struct netadr_s
} netadr_t;
#pragma pack( pop )
STATIC_CHECK_SIZEOF( netadr_t, 20, 20 );
STATIC_ASSERT( sizeof( netadr_t ) == 20, "netadr_t isn't 20 bytes!" );
#endif // NET_ADR_H

View File

@@ -56,8 +56,6 @@ color24 gTracerColors[] =
};
*/
#define TRACER_COLORINDEX_DEFAULT 4
// Temporary entity array
#define TENTPRIORITY_LOW 0
#define TENTPRIORITY_HIGH 1

View File

@@ -28,7 +28,11 @@ typedef byte rgb_t[3]; // unsigned byte colorpack
typedef vec_t matrix3x4[3][4];
typedef vec_t matrix4x4[4][4];
#if XASH_64BIT
typedef uint32_t poolhandle_t;
#else
typedef void* poolhandle_t;
#endif
#undef true
#undef false
@@ -70,64 +74,48 @@ typedef uint64_t longtime_t;
#define IsColorString( p ) ( p && *( p ) == '^' && *(( p ) + 1) && *(( p ) + 1) >= '0' && *(( p ) + 1 ) <= '9' )
#define ColorIndex( c ) ((( c ) - '0' ) & 7 )
#if defined( __GNUC__ )
#if defined( __i386__ )
#define EXPORT __attribute__(( visibility( "default" ), force_align_arg_pointer ))
#define GAME_EXPORT __attribute(( force_align_arg_pointer ))
#if defined(__GNUC__)
#ifdef __i386__
#define EXPORT __attribute__ ((visibility ("default"),force_align_arg_pointer))
#define GAME_EXPORT __attribute((force_align_arg_pointer))
#else
#define EXPORT __attribute__(( visibility ( "default" )))
#define EXPORT __attribute__ ((visibility ("default")))
#define GAME_EXPORT
#endif
#define MALLOC __attribute__(( malloc ))
// added in GCC 11
#if __GNUC__ >= 11
// might want to set noclone due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116893
// but it's easier to not force mismatched-dealloc to error yet
#define MALLOC_LIKE( x, y ) __attribute__(( malloc( x, y )))
#else
#define MALLOC_LIKE( x, y ) MALLOC
#endif
#define NORETURN __attribute__(( noreturn ))
#define NONNULL __attribute__(( nonnull ))
#define _format( x ) __attribute__(( format( printf, x, x + 1 )))
#define ALLOC_CHECK( x ) __attribute__(( alloc_size( x )))
#define NO_ASAN __attribute__(( no_sanitize( "address" )))
#define WARN_UNUSED_RESULT __attribute__(( warn_unused_result ))
#define RENAME_SYMBOL( x ) asm( x )
#else
#if defined( _MSC_VER )
#define EXPORT __declspec( dllexport )
#define NO_ASAN __declspec( no_sanitize_address )
#else
#define EXPORT
#define NO_ASAN
#endif
#define _format(x) __attribute__((format(printf, x, x+1)))
#define NORETURN __attribute__((noreturn))
#define NONNULL __attribute__((nonnull))
#define ALLOC_CHECK(x) __attribute__((alloc_size(x)))
#elif defined(_MSC_VER)
#define EXPORT __declspec( dllexport )
#define GAME_EXPORT
#define _format(x)
#define NORETURN
#define NONNULL
#define _format( x )
#define ALLOC_CHECK( x )
#define RENAME_SYMBOL( x )
#define MALLOC
#define MALLOC_LIKE( x, y )
#define WARN_UNUSED_RESULT
#define ALLOC_CHECK(x)
#else
#define EXPORT
#define GAME_EXPORT
#define _format(x)
#define NORETURN
#define NONNULL
#define ALLOC_CHECK(x)
#endif
#if __GNUC__ >= 3
#define unlikely( x ) __builtin_expect( x, 0 )
#define likely( x ) __builtin_expect( x, 1 )
#if ( __GNUC__ >= 3 )
#define unlikely(x) __builtin_expect(x, 0)
#define likely(x) __builtin_expect(x, 1)
#elif defined( __has_builtin )
#if __has_builtin( __builtin_expect ) // this must be after defined() check
#define unlikely( x ) __builtin_expect( x, 0 )
#define likely( x ) __builtin_expect( x, 1 )
#if __has_builtin( __builtin_expect )
#define unlikely(x) __builtin_expect(x, 0)
#define likely(x) __builtin_expect(x, 1)
#else
#define unlikely(x) (x)
#define likely(x) (x)
#endif
#endif
#if !defined( unlikely ) || !defined( likely )
#define unlikely( x ) ( x )
#define likely( x ) ( x )
#else
#define unlikely(x) (x)
#define likely(x) (x)
#endif
#if __STDC_VERSION__ >= 202311L || __cplusplus >= 201103L // C23 or C++ static_assert is a keyword
@@ -144,23 +132,6 @@ typedef uint64_t longtime_t;
#define STATIC_ASSERT( x, y ) STATIC_ASSERT_2( __LINE__, x, y )
#endif
// at least, statically check size of some public structures
#if XASH_64BIT
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
STATIC_ASSERT( sizeof( type ) == size64, #type " unexpected size" )
#else
#define STATIC_CHECK_SIZEOF( type, size32, size64 ) \
STATIC_ASSERT( sizeof( type ) == size32, #type " unexpected size" )
#endif
#if !defined( __cplusplus ) && __STDC_VERSION__ >= 199101L // not C++ and C99 or newer
#define XASH_RESTRICT restrict
#elif _MSC_VER || __GNUC__ || __clang__ // compiler-specific extensions
#define XASH_RESTRICT __restrict
#else
#define XASH_RESTRICT // nothing
#endif
#ifdef XASH_BIG_ENDIAN
#define LittleLong(x) (((int)(((x)&255)<<24)) + ((int)((((x)>>8)&255)<<16)) + ((int)(((x)>>16)&255)<<8) + (((x) >> 24)&255))
#define LittleLongSW(x) (x = LittleLong(x) )
@@ -191,9 +162,8 @@ _inline float LittleFloat( float f )
#endif
typedef unsigned int dword;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned int dword;
typedef unsigned int uint;
typedef char string[MAX_STRING];
typedef struct file_s file_t; // normal file
typedef struct stream_s stream_t; // sound stream for background music playing

View File

@@ -74,7 +74,7 @@ typedef struct
float size;
} daliashdr_t;
STATIC_CHECK_SIZEOF( daliashdr_t, 84, 84 );
STATIC_ASSERT( sizeof( daliashdr_t ) == 84, "invalid daliashdr_t size" );
typedef struct
{
@@ -83,7 +83,7 @@ typedef struct
int32_t t;
} stvert_t;
STATIC_CHECK_SIZEOF( stvert_t, 12, 12 );
STATIC_ASSERT( sizeof( stvert_t ) == 12, "invalid stvert_t size" );
typedef struct dtriangle_s
{
@@ -91,7 +91,7 @@ typedef struct dtriangle_s
int32_t vertindex[3];
} dtriangle_t;
STATIC_CHECK_SIZEOF( dtriangle_t, 16, 16 );
STATIC_ASSERT( sizeof( dtriangle_t ) == 16, "invalid dtriangle_t size" );
#define DT_FACES_FRONT 0x0010
#define ALIAS_ONSEAM 0x0020
@@ -103,7 +103,7 @@ typedef struct
char name[16]; // frame name from grabbing
} daliasframe_t;
STATIC_CHECK_SIZEOF( daliasframe_t, 24, 24 );
STATIC_ASSERT( sizeof( daliasframe_t ) == 24, "invalid daliasframe_t size" );
typedef struct
{
@@ -112,41 +112,41 @@ typedef struct
trivertex_t bboxmax; // lightnormal isn't used
} daliasgroup_t;
STATIC_CHECK_SIZEOF( daliasgroup_t, 12, 12 );
STATIC_ASSERT( sizeof( daliasgroup_t ) == 12, "invalid daliasgrou_t size" );
typedef struct
{
int32_t numskins;
} daliasskingroup_t;
STATIC_CHECK_SIZEOF( daliasskingroup_t, 4, 4 );
STATIC_ASSERT( sizeof( daliasskingroup_t ) == 4, "invalid daliasskingroup_t size" );
typedef struct
{
float interval;
} daliasinterval_t;
STATIC_CHECK_SIZEOF( daliasinterval_t, 4, 4 );
STATIC_ASSERT( sizeof( daliasinterval_t ) == 4, "invalid daliasinterval_t size" );
typedef struct
{
float interval;
} daliasskininterval_t;
STATIC_CHECK_SIZEOF( daliasskininterval_t, 4, 4 );
STATIC_ASSERT( sizeof( daliasskininterval_t ) == 4, "invalid daliasskininterval_t size" );
typedef struct
{
uint32_t type; // was aliasframetype_t
} daliasframetype_t;
STATIC_CHECK_SIZEOF( daliasframetype_t, 4, 4 );
STATIC_ASSERT( sizeof( daliasframetype_t ) == 4, "invalid daliasframetype_t size" );
typedef struct
{
uint32_t type; // was aliasskintype_t
} daliasskintype_t;
STATIC_CHECK_SIZEOF( daliasskintype_t, 4, 4 );
STATIC_ASSERT( sizeof( daliasskintype_t ) == 4, "invalid daliasskintype_t size" );
#endif//ALIAS_H

View File

@@ -274,13 +274,6 @@ void CL_GenericShot_f( void )
string checkname;
int i;
// allow overriding screenshot by users request
if( Cmd_Argc() > 1 )
{
Q_strncpy( cls.shotname, Cmd_Argv( 1 ), sizeof( cls.shotname ));
break;
}
if( type == scrshot_snapshot )
{
fmt = "../%s_%04d.png";
@@ -356,7 +349,7 @@ void CL_SetSky_f( void )
return;
}
R_SetupSky( Cmd_Argv( 1 ));
ref.dllFuncs.R_SetupSky( Cmd_Argv( 1 ));
}
/*

View File

@@ -70,17 +70,16 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
return true;
}
host.downloadcount++;
if( cl.http_download )
if( cl.downloadUrl[0] )
{
HTTP_AddDownload( filepath, pResource->nDownloadSize, true );
host.downloadcount++;
return false;
}
else
{
MSG_BeginClientCmd( msg, clc_stringcmd );
MSG_WriteStringf( msg, "dlfile %s", filepath );
}
MSG_BeginClientCmd( msg, clc_stringcmd );
MSG_WriteStringf( msg, "dlfile %s", filepath );
host.downloadcount++;
return false;
}
@@ -105,7 +104,7 @@ void CL_AddToResourceList( resource_t *pResource, resource_t *pList )
void CL_RemoveFromResourceList( resource_t *pResource )
{
if( pResource->pPrev == NULL || pResource->pNext == NULL )
Host_Error( "mislinked resource in %s\n", __func__ );
Host_Error( "mislinked resource in CL_RemoveFromResourceList\n" );
if( pResource->pNext == pResource || pResource->pPrev == pResource )
Host_Error( "attempt to free last entry in list.\n" );
@@ -120,7 +119,7 @@ void CL_MoveToOnHandList( resource_t *pResource )
{
if( !pResource )
{
Con_Reportf( "Null resource passed to %s\n", __func__ );
Con_Reportf( "Null resource passed to CL_MoveToOnHandList\n" );
return;
}

View File

@@ -50,29 +50,7 @@ const char *CL_MsgInfo( int cmd )
if( cmd >= 0 && cmd <= svc_lastmsg )
{
// get engine message name
const char *svc_string = NULL;
switch( cls.legacymode )
{
case PROTO_CURRENT:
svc_string = svc_strings[cmd];
break;
case PROTO_LEGACY:
svc_string = svc_legacy_strings[cmd];
break;
case PROTO_QUAKE:
svc_string = svc_quake_strings[cmd];
break;
case PROTO_GOLDSRC:
svc_string = svc_goldsrc_strings[cmd];
break;
}
// fall back to current protocol strings
if( !svc_string )
svc_string = svc_strings[cmd];
Q_strncpy( sz, svc_string, sizeof( sz ));
Q_strncpy( sz, svc_strings[cmd], sizeof( sz ));
}
else if( cmd > svc_lastmsg && cmd <= ( svc_lastmsg + MAX_USER_MESSAGES ))
{

View File

@@ -40,8 +40,6 @@ GNU General Public License for more details.
#define IDEMOHEADER (('M'<<24)+('E'<<16)+('D'<<8)+'I') // little-endian "IDEM"
#define DEMO_PROTOCOL 3
#define PROTOCOL_GOLDSRC_VERSION_DEMO (PROTOCOL_GOLDSRC_VERSION | (BIT( 7 ))) // should be 48, only to differentiate it from PROTOCOL_LEGACY_VERSION
const char *demo_cmd[dem_lastcmd+1] =
{
"dem_unknown",
@@ -81,7 +79,7 @@ typedef struct
typedef struct
{
demoentry_t *entries; // track entry info
int32_t numentries; // number of tracks
int numentries; // number of tracks
} demodirectory_t;
// add angles
@@ -111,40 +109,6 @@ struct
static qboolean CL_NextDemo( void );
static int CL_GetDemoNetProtocol( connprotocol_t proto )
{
switch( proto )
{
case PROTO_CURRENT:
return PROTOCOL_VERSION;
case PROTO_LEGACY:
return PROTOCOL_LEGACY_VERSION;
case PROTO_QUAKE:
return PROTOCOL_VERSION_QUAKE;
case PROTO_GOLDSRC:
return PROTOCOL_GOLDSRC_VERSION_DEMO;
}
return PROTOCOL_VERSION;
}
static connprotocol_t CL_GetProtocolFromDemo( int net_protocol )
{
switch( net_protocol )
{
case PROTOCOL_VERSION:
return PROTO_CURRENT;
case PROTOCOL_LEGACY_VERSION:
return PROTO_LEGACY;
case PROTOCOL_VERSION_QUAKE:
return PROTO_QUAKE;
case PROTOCOL_GOLDSRC_VERSION_DEMO:
return PROTO_GOLDSRC;
}
return PROTO_CURRENT;
}
/*
====================
CL_StartupDemoHeader
@@ -155,8 +119,12 @@ we record a demo on this level
*/
void CL_StartupDemoHeader( void )
{
CL_CloseDemoHeader();
if( cls.demoheader )
{
FS_Close( cls.demoheader );
}
// Note: this is replacing tmpfile()
cls.demoheader = FS_Open( "demoheader.tmp", "w+b", true );
if( !cls.demoheader )
@@ -329,6 +297,10 @@ void CL_WriteDemoMessage( qboolean startup, int start, sizebuf_t *msg )
if( !file ) return;
// past the start but not recording a demo.
if( !startup && !cls.demorecording )
return;
swlen = MSG_GetNumBytesWritten( msg ) - start;
if( swlen <= 0 ) return;
@@ -401,7 +373,7 @@ static void CL_WriteDemoHeader( const char *name )
demo.header.id = IDEMOHEADER;
demo.header.dem_protocol = DEMO_PROTOCOL;
demo.header.net_protocol = CL_GetDemoNetProtocol( cls.legacymode );
demo.header.net_protocol = cls.legacymode ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION;
demo.header.host_fps = host_maxfps.value ? bound( MIN_FPS, host_maxfps.value, MAX_FPS ) : MAX_FPS;
Q_strncpy( demo.header.mapname, clgame.mapname, sizeof( demo.header.mapname ));
Q_strncpy( demo.header.comment, clgame.maptitle, sizeof( demo.header.comment ));
@@ -421,7 +393,6 @@ static void CL_WriteDemoHeader( const char *name )
// finish off the startup info.
CL_WriteDemoCmdHeader( dem_stop, cls.demoheader );
FS_Flush( cls.demoheader );
// now copy the stuff we cached from the server.
copysize = savepos = FS_Tell( cls.demoheader );
@@ -708,7 +679,7 @@ static void CL_DemoStartPlayback( int mode )
demo.starttime = CL_GetDemoPlaybackClock(); // for determining whether to read another message
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize, 0 );
Netchan_Setup( NS_CLIENT, &cls.netchan, net_from, Cvar_VariableInteger( "net_qport" ), NULL, CL_GetFragmentSize );
memset( demo.cmds, 0, sizeof( demo.cmds ));
demo.angle_position = 1;
@@ -1148,7 +1119,6 @@ show stats
*/
static void CL_FinishTimeDemo( void )
{
qboolean temp = host.allow_console;
int frames;
double time;
@@ -1159,9 +1129,7 @@ static void CL_FinishTimeDemo( void )
time = host.realtime - cls.td_starttime;
if( !time ) time = 1.0;
host.allow_console = true;
Con_Printf( "timedemo result: %i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
host.allow_console = temp;
if( Sys_CheckParm( "-timedemo" ))
CL_Quit_f();
@@ -1450,51 +1418,6 @@ void CL_Record_f( void )
CL_WriteDemoHeader( demopath );
}
static qboolean CL_ParseDemoHeader( const char *callee, const char *filename, file_t *f, demoheader_t *hdr, int32_t *numentries )
{
if( FS_Read( f, hdr, sizeof( *hdr )) != sizeof( *hdr ) || hdr->id != IDEMOHEADER )
{
Con_Printf( S_ERROR "%s: %s is not in supported format or not a demo file\n", callee, filename );
return false;
}
// force null terminate strings
hdr->mapname[sizeof( hdr->mapname ) - 1] = 0;
hdr->comment[sizeof( hdr->comment ) - 1] = 0;
hdr->gamedir[sizeof( hdr->gamedir ) - 1] = 0;
if( hdr->dem_protocol != DEMO_PROTOCOL )
{
Con_Printf( S_ERROR "%s: demo protocol outdated (%i should be %i)\n",
callee, hdr->net_protocol, DEMO_PROTOCOL );
return false;
}
if( hdr->net_protocol != PROTOCOL_VERSION && hdr->net_protocol != PROTOCOL_LEGACY_VERSION )
{
Con_Printf( S_ERROR "%s: net protocol outdated (%i should be %i or %i)\n",
callee, hdr->net_protocol, PROTOCOL_VERSION, PROTOCOL_LEGACY_VERSION );
return false;
}
if( FS_Seek( f, hdr->directory_offset, SEEK_SET ) < 0
|| FS_Read( f, numentries, sizeof( *numentries )) != sizeof( *numentries ))
{
Con_Printf( S_ERROR "%s: can't find directory offset in %s, demo file corrupted\n",
callee, filename );
return false;
}
if(( *numentries < 1 ) || ( *numentries > 1024 ))
{
Con_Printf( S_ERROR "%s: demo have bogus # of directory entries: %i\n",
callee, *numentries );
return false;
}
return true;
}
/*
====================
CL_PlayDemo_f
@@ -1515,7 +1438,9 @@ void CL_PlayDemo_f( void )
}
if( cls.demoplayback )
{
CL_StopPlayback();
}
if( cls.demorecording )
{
@@ -1565,32 +1490,51 @@ void CL_PlayDemo_f( void )
if( neg ) cls.forcetrack = -cls.forcetrack;
CL_DemoStartPlayback( DEMO_QUAKE1 );
cls.legacymode = PROTO_QUAKE;
return; // quake demo is started
}
// read in the demo header
if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, cls.demofile, &demo.header, &demo.directory.numentries ))
FS_Read( cls.demofile, &demo.header, sizeof( demoheader_t ));
if( demo.header.id != IDEMOHEADER )
{
Con_Printf( S_ERROR "%s is not a demo file\n", demoname );
CL_DemoAborted();
return;
}
if( demo.header.dem_protocol != DEMO_PROTOCOL )
{
Con_Printf( S_ERROR "playdemo: demo protocol outdated (%i should be %i)\n", demo.header.dem_protocol, DEMO_PROTOCOL );
CL_DemoAborted();
return;
}
if( demo.header.net_protocol != PROTOCOL_VERSION &&
demo.header.net_protocol != PROTOCOL_LEGACY_VERSION )
{
Con_Printf( S_ERROR "playdemo: net protocol outdated (%i should be %i)\n", demo.header.net_protocol, PROTOCOL_VERSION );
CL_DemoAborted();
return;
}
// now read in the directory structure.
FS_Seek( cls.demofile, demo.header.directory_offset, SEEK_SET );
FS_Read( cls.demofile, &demo.directory.numentries, sizeof( int ));
if( demo.directory.numentries < 1 || demo.directory.numentries > 1024 )
{
Con_Printf( S_ERROR "demo had bogus # of directory entries: %i\n", demo.directory.numentries );
CL_DemoAborted();
return;
}
// allocate demo entries
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( *demo.directory.entries ) * demo.directory.numentries );
demo.directory.entries = Mem_Malloc( cls.mempool, sizeof( demoentry_t ) * demo.directory.numentries );
for( i = 0; i < demo.directory.numentries; i++ )
{
demoentry_t *entry = &demo.directory.entries[i];
if( FS_Read( cls.demofile, entry, sizeof( *entry )) != sizeof( *entry ))
{
Con_Printf( S_ERROR "%s: demo entry %i of %s corrupted", Cmd_Argv( 0 ), i, filename );
CL_DemoAborted();
return;
}
entry->description[sizeof( entry->description ) - 1] = 0;
FS_Read( cls.demofile, &demo.directory.entries[i], sizeof( demoentry_t ));
}
demo.entryIndex = 0;
@@ -1600,11 +1544,9 @@ void CL_PlayDemo_f( void )
CL_DemoStartPlayback( DEMO_XASH3D );
// must be after DemoStartPlayback, as CL_Disconnect_f resets the protocol
cls.legacymode = CL_GetProtocolFromDemo( demo.header.net_protocol );
// g-cont. is this need?
Q_strncpy( cls.servername, demoname, sizeof( cls.servername ));
cls.legacymode = demo.header.net_protocol == PROTOCOL_LEGACY_VERSION;
// begin a playback demo
}
@@ -1646,7 +1588,7 @@ void CL_StartDemos_f( void )
c = Cmd_Argc() - 1;
if( c > MAX_DEMOS )
{
Con_DPrintf( S_WARN "%s: max %i demos in demoloop\n", __func__, MAX_DEMOS );
Con_DPrintf( S_WARN "Host_StartDemos: max %i demos in demoloop\n", MAX_DEMOS );
c = MAX_DEMOS;
}
@@ -1704,78 +1646,3 @@ void CL_Stop_f( void )
S_StopBackgroundTrack();
}
}
void CL_ListDemo_f( void )
{
demoheader_t hdr;
int32_t num_entries;
file_t *f;
char filename[MAX_QPATH];
char demoname[MAX_QPATH];
int i;
if( Cmd_Argc() < 2 )
{
Con_Printf( S_USAGE "%s <demoname>\n", Cmd_Argv( 0 ));
return;
}
Q_strncpy( demoname, Cmd_Argv( 1 ), sizeof( demoname ));
COM_StripExtension( demoname );
Q_snprintf( filename, sizeof( filename ), "%s.dem", demoname );
f = FS_Open( filename, "rb", true );
if( !f )
{
Con_Printf( S_ERROR "couldn't open %s\n", filename );
return;
}
if( !CL_ParseDemoHeader( Cmd_Argv( 0 ), filename, f, &hdr, &num_entries ))
{
FS_Close( f );
return;
}
Con_Printf( "Demo contents for %s:\n"
"\tProtocol: %i net/%i demo\n"
"\tFPS: %g\n"
"\tMap: %s\n"
"\tComment: %s\n"
"\tGame: %s\n",
filename, hdr.net_protocol, hdr.dem_protocol, hdr.host_fps, hdr.mapname,
hdr.comment, hdr.gamedir );
for( i = 0; i < num_entries; i++ )
{
demoentry_t entry;
Con_Printf( "Demo entry #%i:\n", i );
if( FS_Read( f, &entry, sizeof( entry )) != sizeof( entry ))
{
Con_Printf( S_ERROR "can't read demo entry\n" );
FS_Close( f );
return;
}
entry.description[sizeof( entry.description ) - 1] = 0;
if( entry.entrytype == DEMO_STARTUP )
{
// startup entries don't have anything useful
Con_Printf( "\tEntry type: " S_YELLOW "startup" S_DEFAULT "\n" );
}
else
{
Con_Printf( "\tEntry type: " S_GREEN "normal" S_DEFAULT " (%i)\n"
"\tEntry playback time/frames: %.2f seconds/%i frames\n"
"\tEntry flags: 0x%x\n"
"\tEntry description: %s\n",
entry.entrytype, entry.playback_time, entry.playback_frames,
entry.flags, entry.description );
}
}
FS_Close( f );
}

View File

@@ -28,51 +28,10 @@ GNU General Public License for more details.
===============================================================================
*/
#define NUM_EFRAGS_ALLOC 64 // alloc 64 efrags (1-2kb each alloc)
static efrag_t **lastlink;
static mnode_t *r_pefragtopnode;
static vec3_t r_emins, r_emaxs;
static cl_entity_t *r_addent;
static int cl_efrags_num;
static efrag_t *cl_efrags;
static efrag_t *CL_AllocEfrags( int num )
{
int i;
efrag_t *efrags;
if( !cl.worldmodel )
{
Host_Error( "%s: called with NULL world\n", __func__ );
return NULL;
}
if( num == 0 )
return NULL;
// set world to be the owner, so it will get automatically cleaned up
efrags = Mem_Calloc( cl.worldmodel->mempool, sizeof( *efrags ) * num );
// initialize linked list
for( i = 0; i < num - 1; i++ )
efrags[i].entnext = &efrags[i + 1];
cl_efrags_num += num;
return efrags;
}
/*
==============
CL_ClearEfrags
==============
*/
void CL_ClearEfrags( void )
{
cl_efrags_num = 0;
cl_efrags = NULL;
}
/*
===================
@@ -97,11 +56,14 @@ static void R_SplitEntityOnNode( mnode_t *node )
leaf = (mleaf_t *)node;
// grab an efrag off the free list
ef = cl_efrags;
ef = clgame.free_efrags;
if( !ef )
ef = CL_AllocEfrags( NUM_EFRAGS_ALLOC );
{
Con_Printf( S_ERROR "too many efrags!\n" );
return; // no free fragments...
}
cl_efrags = ef->entnext;
clgame.free_efrags = ef->entnext;
ef->entity = r_addent;
// add the entity link
@@ -171,29 +133,35 @@ R_StoreEfrags
*/
void R_StoreEfrags( efrag_t **ppefrag, int framecount )
{
efrag_t *pefrag;
cl_entity_t *pent;
model_t *clmodel;
cl_entity_t *pent;
model_t *clmodel;
efrag_t *pefrag;
while(( pefrag = *ppefrag ) != NULL )
{
pent = pefrag->entity;
clmodel = pent->model;
// how this could happen?
if( unlikely( clmodel->type < mod_brush || clmodel->type > mod_studio ))
continue;
if( pent->visframe != framecount )
switch( clmodel->type )
{
if( CL_AddVisibleEntity( pent, ET_FRAGMENTED ))
case mod_alias:
case mod_brush:
case mod_studio:
case mod_sprite:
if( pent->visframe != framecount )
{
// mark that we've recorded this entity for this frame
pent->curstate.messagenum = cl.parsecount;
pent->visframe = framecount;
if( CL_AddVisibleEntity( pent, ET_FRAGMENTED ))
{
// mark that we've recorded this entity for this frame
pent->curstate.messagenum = cl.parsecount;
pent->visframe = framecount;
}
}
}
ppefrag = &pefrag->leafnext;
ppefrag = &pefrag->leafnext;
break;
default:
break;
}
}
}

View File

@@ -25,16 +25,13 @@ static CVAR_DEFINE_AUTO( tracerspeed, "6000", 0, "tracer speed" );
static CVAR_DEFINE_AUTO( tracerlength, "0.8", 0, "tracer length factor" );
static CVAR_DEFINE_AUTO( traceroffset, "30", 0, "tracer starting offset" );
static particle_t *cl_active_particles;
static particle_t *cl_active_tracers;
static particle_t *cl_free_particles;
static particle_t *cl_particles = NULL; // particle pool
particle_t *cl_active_particles;
particle_t *cl_active_tracers;
particle_t *cl_free_particles;
particle_t *cl_particles = NULL; // particle pool
static vec3_t cl_avelocities[NUMVERTEXNORMALS];
static float cl_lasttimewarn = 0.0f;
// expand debugging BBOX particle hulls by this many units.
#define BOX_GAP 0.0f
/*
================
R_LookupColor
@@ -253,7 +250,7 @@ static particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life
VectorCopy( vel, p->vel );
p->die = cl.time + life;
p->ramp = tracerlength.value;
p->color = TRACER_COLORINDEX_DEFAULT; // select custom color
p->color = 4; // select custom color
p->packedColor = 255; // alpha
return p;
@@ -265,9 +262,9 @@ VIEWBEAMS MANAGEMENT
==============================================================
*/
static BEAM *cl_active_beams;
static BEAM *cl_free_beams;
static BEAM *cl_viewbeams = NULL; // beams pool
BEAM *cl_active_beams;
BEAM *cl_free_beams;
BEAM *cl_viewbeams = NULL; // beams pool
/*
@@ -639,24 +636,12 @@ and all particle trails (if this is a beamfollow)
*/
void GAME_EXPORT R_BeamKill( int deadEntity )
{
BEAM *beam;
cl_entity_t *pDeadEntity;
for( beam = cl_active_beams; beam; beam = beam->next )
{
if( FBitSet( beam->flags, FBEAM_STARTENTITY ) && beam->startEntity == deadEntity )
{
if( beam->type != TE_BEAMFOLLOW )
beam->die = cl.time;
pDeadEntity = R_BeamGetEntity( deadEntity );
if( !pDeadEntity ) return;
ClearBits( beam->flags, FBEAM_STARTENTITY );
}
if( FBitSet( beam->flags, FBEAM_ENDENTITY ) && beam->endEntity == deadEntity )
{
beam->die = cl.time;
ClearBits( beam->flags, FBEAM_ENDENTITY );
}
}
CL_KillDeadBeams( pDeadEntity );
}
/*
@@ -1109,7 +1094,9 @@ void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int col
int colorMod = 0, packedColor;
particle_t *p;
packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
packedColor = 255; // use old code for blob particles
else packedColor = 0;
for( i = 0; i < 512; i++ )
{
@@ -1142,7 +1129,9 @@ void GAME_EXPORT R_BlobExplosion( const vec3_t org )
particle_t *p;
int i, j, packedColor;
packedColor = Host_IsQuakeCompatible( ) ? 255 : 0; // use old code for blob particles
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
packedColor = 255; // use old code for blob particles
else packedColor = 0;
for( i = 0; i < 1024; i++ )
{
@@ -1604,73 +1593,6 @@ void GAME_EXPORT R_RocketTrail( vec3_t start, vec3_t end, int type )
}
}
/*
===============
PM_ParticleLine
draw line from particles
================
*/
static void PM_ParticleLine( const vec3_t start, const vec3_t end, int pcolor, float life, float zvel )
{
float len, curdist;
vec3_t diff, pos;
// determine distance
VectorSubtract( end, start, diff );
len = VectorNormalizeLength( diff );
curdist = 0;
while( curdist <= len )
{
VectorMA( start, curdist, diff, pos );
CL_Particle( pos, pcolor, life, 0, zvel );
curdist += 2.0f;
}
}
/*
================
PM_DrawRectangle
================
*/
static void PM_DrawRectangle( const vec3_t tl, const vec3_t bl, const vec3_t tr, const vec3_t br, int pcolor, float life )
{
PM_ParticleLine( tl, bl, pcolor, life, 0 );
PM_ParticleLine( bl, br, pcolor, life, 0 );
PM_ParticleLine( br, tr, pcolor, life, 0 );
PM_ParticleLine( tr, tl, pcolor, life, 0 );
}
/*
================
PM_DrawBBox
================
*/
static void PM_DrawBBox( const vec3_t mins, const vec3_t maxs, const vec3_t origin, int pcolor, float life )
{
vec3_t p[8], tmp;
float gap = BOX_GAP;
int i;
for( i = 0; i < 8; i++ )
{
tmp[0] = (i & 1) ? mins[0] - gap : maxs[0] + gap;
tmp[1] = (i & 2) ? mins[1] - gap : maxs[1] + gap ;
tmp[2] = (i & 4) ? mins[2] - gap : maxs[2] + gap ;
VectorAdd( tmp, origin, tmp );
VectorCopy( tmp, p[i] );
}
for( i = 0; i < 6; i++ )
{
PM_DrawRectangle( p[boxpnt[i][1]], p[boxpnt[i][0]], p[boxpnt[i][2]], p[boxpnt[i][3]], pcolor, life );
}
}
/*
================
R_ParticleLine
@@ -1834,6 +1756,25 @@ void GAME_EXPORT R_StreakSplash( const vec3_t pos, const vec3_t dir, int color,
}
}
/*
===============
R_DebugParticle
just for debug purposes
===============
*/
void R_DebugParticle( const vec3_t pos, byte r, byte g, byte b )
{
particle_t *p;
p = R_AllocParticle( NULL );
if( !p ) return;
VectorCopy( pos, p->org );
p->color = R_LookupColor( r, g, b );
p->die = cl.time + 0.01f;
}
/*
===============
CL_Particle

View File

@@ -192,7 +192,7 @@ void CL_RegisterEvent( int lastnum, const char *szEvName, pfnEventHook func )
ev = clgame.events[lastnum];
// NOTE: ev->index will be set later
Q_strncpy( ev->name, szEvName, sizeof( ev->name ));
Q_strncpy( ev->name, szEvName, MAX_QPATH );
ev->func = func;
}
@@ -219,7 +219,7 @@ static qboolean CL_FireEvent( event_info_t *ei, int slot )
if( !ev )
{
idx = bound( 1, ei->index, ( MAX_EVENTS - 1 ));
Con_Reportf( S_ERROR "%s: %s not precached\n", __func__, cl.event_precache[idx] );
Con_Reportf( S_ERROR "CL_FireEvent: %s not precached\n", cl.event_precache[idx] );
break;
}
@@ -244,7 +244,7 @@ static qboolean CL_FireEvent( event_info_t *ei, int slot )
return true;
}
Con_Reportf( S_ERROR "%s: %s not hooked\n", __func__, name );
Con_Reportf( S_ERROR "CL_FireEvent: %s not hooked\n", name );
break;
}
}
@@ -380,7 +380,7 @@ CL_ParseReliableEvent
=============
*/
void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto )
void CL_ParseReliableEvent( sizebuf_t *msg )
{
int event_index;
event_args_t nullargs, args;
@@ -390,19 +390,11 @@ void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto )
event_index = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
// reliable events not use delta-compression just null-compression
if( proto == PROTO_GOLDSRC )
{
Delta_ReadGSFields( msg, DT_EVENT_T, &nullargs, &args, 0.0f );
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
}
else
{
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
MSG_ReadDeltaEvent( msg, &nullargs, &args );
}
MSG_ReadDeltaEvent( msg, &nullargs, &args );
if( args.entindex > 0 && args.entindex <= cl.maxclients )
args.angles[PITCH] *= -3.0f;
@@ -417,43 +409,34 @@ CL_ParseEvent
=============
*/
void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto )
void CL_ParseEvent( sizebuf_t *msg )
{
int event_index;
int i, num_events;
int packet_index;
const event_args_t nullargs = { 0 };
event_args_t args = { 0 };
event_args_t nullargs, args;
entity_state_t *state;
float delay;
int entity_bits;
memset( &nullargs, 0, sizeof( nullargs ));
memset( &args, 0, sizeof( args ));
num_events = MSG_ReadUBitLong( msg, 5 );
if( proto == PROTO_GOLDSRC )
entity_bits = MAX_GOLDSRC_ENTITY_BITS;
else if( proto == PROTO_LEGACY )
entity_bits = MAX_LEGACY_ENTITY_BITS;
else entity_bits = MAX_ENTITY_BITS;
// parse events queue
for( i = 0 ; i < num_events; i++ )
{
event_index = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
if( MSG_ReadOneBit( msg ))
{
packet_index = MSG_ReadUBitLong( msg, entity_bits );
if( MSG_ReadOneBit( msg ))
{
if( proto == PROTO_GOLDSRC )
Delta_ReadGSFields( msg, DT_EVENT_T, &nullargs, &args, 0.0f );
else MSG_ReadDeltaEvent( msg, &nullargs, &args );
}
}
packet_index = MSG_ReadUBitLong( msg, cls.legacymode ? MAX_LEGACY_ENTITY_BITS : MAX_ENTITY_BITS );
else packet_index = -1;
if( MSG_ReadOneBit( msg ))
{
MSG_ReadDeltaEvent( msg, &nullargs, &args );
}
if( MSG_ReadOneBit( msg ))
delay = (float)MSG_ReadWord( msg ) * (1.0f / 100.0f);
else delay = 0.0f;
@@ -514,14 +497,14 @@ void GAME_EXPORT CL_PlaybackEvent( int flags, const edict_t *pInvoker, word even
// first check event for out of bounds
if( eventindex < 1 || eventindex >= MAX_EVENTS )
{
Con_DPrintf( S_ERROR "%s: invalid eventindex %i\n", __func__, eventindex );
Con_DPrintf( S_ERROR "CL_PlaybackEvent: invalid eventindex %i\n", eventindex );
return;
}
// check event for precached
if( !CL_EventIndex( cl.event_precache[eventindex] ))
{
Con_DPrintf( S_ERROR "%s: event %i was not precached\n", __func__, eventindex );
Con_DPrintf( S_ERROR "CL_PlaybackEvent: event %i was not precached\n", eventindex );
return;
}

View File

@@ -95,7 +95,8 @@ static void CL_ResetPositions( cl_entity_t *ent )
ent->current_position = 1;
memset( ent->ph, 0, sizeof( position_history_t ) * HISTORY_MAX );
ent->ph[1] = ent->ph[0] = store;
memcpy( &ent->ph[1], &store, sizeof( position_history_t ));
memcpy( &ent->ph[0], &store, sizeof( position_history_t ));
}
/*
@@ -174,7 +175,7 @@ static qboolean CL_EntityCustomLerp( cl_entity_t *e )
// INTERPOLATION IN GRAVGUNMOD COOP
// MUST BE REMOVED ONCE WE REMOVE 48 PROTO SUPPORT
case MOVETYPE_TOSS:
if( cls.legacymode == PROTO_LEGACY && e->model && e->model->type == mod_studio )
if( cls.legacymode && e->model && e->model->type == mod_studio )
return false;
}
@@ -669,9 +670,9 @@ FRAME PARSING
=========================================================================
*/
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum, connprotocol_t proto )
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum )
{
if( proto == PROTO_LEGACY )
if( cls.legacymode )
{
*newnum = MSG_ReadWord( msg );
if( *newnum == 0 )
@@ -694,7 +695,7 @@ CL_FlushEntityPacket
Read and ignore whole entity packet.
=================
*/
static void CL_FlushEntityPacket( sizebuf_t *msg, connprotocol_t proto )
static void CL_FlushEntityPacket( sizebuf_t *msg )
{
int newnum;
entity_state_t from, to;
@@ -707,57 +708,16 @@ static void CL_FlushEntityPacket( sizebuf_t *msg, connprotocol_t proto )
// read it all, but ignore it
while( 1 )
{
if( !CL_ParseEntityNumFromPacket( msg, &newnum, proto ))
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
break; // done
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
Host_Error( "CL_FlushEntityPacket: overflow\n" );
MSG_ReadDeltaEntity( msg, &from, &to, newnum, CL_IsPlayerIndex( newnum ) ? DELTA_PLAYER : DELTA_ENTITY, cl.mtime[0] );
}
}
qboolean CL_ValidateDeltaPacket( uint oldpacket, frame_t *oldframe )
{
int subtracted = ( cls.netchan.incoming_sequence - oldpacket ) & 0xFF;
if( subtracted == 0 )
{
Con_NPrintf( 2, "^3Warning:^1 update too old\n^7\n" );
return false;
}
if( subtracted >= CL_UPDATE_MASK )
{
// we can't use this, it is too old
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
return false;
}
if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - NUM_PACKET_ENTITIES ))
{
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
return false;
}
return true;
}
int CL_UpdateOldEntNum( int oldindex, frame_t *oldframe, entity_state_t **oldent )
{
if( !oldframe )
{
*oldent = NULL;
return MAX_ENTNUMBER;
}
if( oldindex >= oldframe->num_entities )
return MAX_ENTNUMBER;
*oldent = &cls.packet_entities[(oldframe->first_entity + oldindex) % cls.num_client_entities];
return (*oldent)->number;
}
/*
=================
CL_DeltaEntity
@@ -780,7 +740,7 @@ static void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_s
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
{
Con_DPrintf( S_ERROR "%s: invalid newnum: %d\n", __func__, newnum );
Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum );
if( has_update )
MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] );
return;
@@ -792,7 +752,7 @@ static void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_s
if( has_update )
alive = MSG_ReadDeltaEntity( msg, old, state, newnum, delta_type, cl.mtime[0] );
else *state = *old;
else memcpy( state, old, sizeof( entity_state_t ));
if( !alive )
{
@@ -828,7 +788,7 @@ An svc_packetentities has just been parsed, deal with the
rest of the data stream.
==================
*/
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto )
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
{
frame_t *newframe, *oldframe;
int oldindex, newnum, oldnum;
@@ -844,7 +804,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto
CL_WriteDemoJumpTime();
// sentinel count. save it for debug checking
if( proto == PROTO_LEGACY )
if( cls.legacymode )
count = MSG_ReadWord( msg );
else count = MSG_ReadUBitLong( msg, MAX_VISIBLE_PACKET_BITS ) + 1;
@@ -858,12 +818,32 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto
if( delta )
{
uint oldpacket = MSG_ReadByte( msg );
int subtracted;
oldpacket = MSG_ReadByte( msg );
subtracted = ( cls.netchan.incoming_sequence - oldpacket ) & 0xFF;
if( subtracted == 0 )
{
Con_NPrintf( 2, "^3Warning:^1 update too old\n^7\n" );
CL_FlushEntityPacket( msg );
return playerbytes;
}
if( subtracted >= CL_UPDATE_MASK )
{
// we can't use this, it is too old
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
CL_FlushEntityPacket( msg );
return playerbytes;
}
oldframe = &cl.frames[oldpacket & CL_UPDATE_MASK];
if( !CL_ValidateDeltaPacket( oldpacket, oldframe ))
if(( cls.next_client_entities - oldframe->first_entity ) > ( cls.num_client_entities - NUM_PACKET_ENTITIES ))
{
CL_FlushEntityPacket( msg, proto );
Con_NPrintf( 2, "^3Warning:^1 delta frame is too old^7\n" );
CL_FlushEntityPacket( msg );
return playerbytes;
}
}
@@ -881,15 +861,31 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto
oldent = NULL;
oldindex = 0;
oldnum = CL_UpdateOldEntNum( oldindex, oldframe, &oldent );
if( !oldframe )
{
oldnum = MAX_ENTNUMBER;
}
else
{
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
}
while( 1 )
{
if( !CL_ParseEntityNumFromPacket( msg, &newnum, proto ))
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
break; // done
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
Host_Error( "CL_ParsePacketEntities: overflow\n" );
player = CL_IsPlayerIndex( newnum );
@@ -897,7 +893,17 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto
{
// one or more entities from the old packet are unchanged
CL_DeltaEntity( msg, newframe, oldnum, oldent, false );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
oldindex++;
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
}
if( oldnum == newnum )
@@ -906,7 +912,17 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto
bufStart = MSG_GetNumBytesRead( msg );
CL_DeltaEntity( msg, newframe, newnum, oldent, true );
if( player ) playerbytes += MSG_GetNumBytesRead( msg ) - bufStart;
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
oldindex++;
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
continue;
}
@@ -925,11 +941,21 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto
{
// one or more entities from the old packet are unchanged
CL_DeltaEntity( msg, newframe, oldnum, oldent, false );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
oldindex++;
if( oldindex >= oldframe->num_entities )
{
oldnum = MAX_ENTNUMBER;
}
else
{
oldent = &cls.packet_entities[(oldframe->first_entity+oldindex) % cls.num_client_entities];
oldnum = oldent->number;
}
}
if( newframe->num_entities != count && newframe->num_entities != 0 )
Con_Reportf( S_WARN "%s%s: (%i should be %i)\n", __func__, delta ? "Delta" : "", newframe->num_entities, count );
Con_Reportf( S_WARN "CL_Parse%sPacketEntities: (%i should be %i)\n", delta ? "Delta" : "", newframe->num_entities, count );
if( !newframe->valid )
return playerbytes; // frame is not valid but message was parsed
@@ -947,7 +973,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto
cls.signon = SIGNONS;
// Clear loading plaque.
CL_SignonReply( proto );
CL_SignonReply ();
}
return playerbytes;
@@ -1161,7 +1187,7 @@ static void CL_LinkPacketEntities( frame_t *frame )
if( !ent )
{
Con_Reportf( S_ERROR "%s: bad entity %i\n", __func__, state->number );
Con_Reportf( S_ERROR "CL_LinkPacketEntity: bad entity %i\n", state->number );
continue;
}
@@ -1265,7 +1291,7 @@ static void CL_LinkPacketEntities( frame_t *frame )
// ABSOLUTELY STUPID HACK TO ALLOW MONSTERS
// INTERPOLATION IN GRAVGUNMOD COOP
// MUST BE REMOVED ONCE WE REMOVE 48 PROTO SUPPORT
else if( cls.legacymode == PROTO_LEGACY && ent->model->type == mod_studio && ent->curstate.movetype == MOVETYPE_TOSS )
else if( cls.legacymode && ent->model->type == mod_studio && ent->curstate.movetype == MOVETYPE_TOSS )
{
if( !CL_InterpolateModel( ent ))
continue;

View File

@@ -34,10 +34,10 @@ GNU General Public License for more details.
#define MAX_TEXTCHANNELS 8 // must be power of two (GoldSrc uses 4 channels)
#define TEXT_MSGNAME "TextMessage%i"
static char cl_textbuffer[MAX_TEXTCHANNELS][2048];
static client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS];
char cl_textbuffer[MAX_TEXTCHANNELS][2048];
client_textmessage_t cl_textmessage[MAX_TEXTCHANNELS];
static const dllfunc_t cdll_exports[] =
static dllfunc_t cdll_exports[] =
{
{ "Initialize", (void **)&clgame.dllFuncs.pfnInitialize },
{ "HUD_VidInit", (void **)&clgame.dllFuncs.pfnVidInit },
@@ -80,7 +80,7 @@ static const dllfunc_t cdll_exports[] =
};
// optional exports
static const dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and higher
static dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and higher
{
{ "HUD_GetStudioModelInterface", (void **)&clgame.dllFuncs.pfnGetStudioModelInterface },
{ "HUD_DirectorMessage", (void **)&clgame.dllFuncs.pfnDirectorMessage },
@@ -140,7 +140,11 @@ returns true if thirdperson is enabled
*/
qboolean CL_IsThirdPerson( void )
{
return clgame.dllFuncs.CL_IsThirdPerson() ? true : false;
cl.local.thirdperson = clgame.dllFuncs.CL_IsThirdPerson();
if( cl.local.thirdperson )
return true;
return false;
}
/*
@@ -227,7 +231,7 @@ static void CL_InitCDAudio( const char *filename )
if( ++c > MAX_CDTRACKS - 1 )
{
Con_Reportf( S_WARN "%s: too many tracks %i in %s\n", __func__, MAX_CDTRACKS, filename );
Con_Reportf( S_WARN "CD_Init: too many tracks %i in %s\n", MAX_CDTRACKS, filename );
break;
}
}
@@ -248,18 +252,18 @@ static int CL_AdjustXPos( float x, int width, int totalWidth )
if( x == -1 )
{
xPos = ( clgame.scrInfo.iWidth - width ) * 0.5f;
xPos = ( refState.width - width ) * 0.5f;
}
else
{
if ( x < 0 )
xPos = (1.0f + x) * clgame.scrInfo.iWidth - totalWidth; // Alight right
xPos = (1.0f + x) * refState.width - totalWidth; // Alight right
else // align left
xPos = x * clgame.scrInfo.iWidth;
xPos = x * refState.width;
}
if( xPos + width > clgame.scrInfo.iWidth )
xPos = clgame.scrInfo.iWidth - width;
if( xPos + width > refState.width )
xPos = refState.width - width;
else if( xPos < 0 )
xPos = 0;
@@ -279,19 +283,19 @@ static int CL_AdjustYPos( float y, int height )
if( y == -1 ) // centered?
{
yPos = ( clgame.scrInfo.iHeight - height ) * 0.5f;
yPos = ( refState.height - height ) * 0.5f;
}
else
{
// Alight bottom?
if( y < 0 )
yPos = (1.0f + y) * clgame.scrInfo.iHeight - height; // Alight bottom
yPos = (1.0f + y) * refState.height - height; // Alight bottom
else // align top
yPos = y * clgame.scrInfo.iHeight;
yPos = y * refState.height;
}
if( yPos + height > clgame.scrInfo.iHeight )
yPos = clgame.scrInfo.iHeight - height;
if( yPos + height > refState.height )
yPos = refState.height - height;
else if( yPos < 0 )
yPos = 0;
@@ -556,19 +560,7 @@ static void CL_DrawScreenFade( void )
if( !alpha )
return;
if( !FBitSet( sf->fadeFlags, FFADE_MODULATE ))
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
}
else if( Host_IsQuakeCompatible( ))
{
// Quake Wrapper and Quake Remake use FFADE_MODULATE for item pickups
// so hack the check here
ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd );
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
}
else
if( FBitSet( sf->fadeFlags, FFADE_MODULATE ))
{
ref.dllFuncs.GL_SetRenderMode( kRenderScreenFadeModulate );
@@ -578,6 +570,11 @@ static void CL_DrawScreenFade( void )
(uint16_t)( sf->fadeb * alpha + ( 255 - alpha ) * 255 ) >> 8,
255 );
}
else
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
ref.dllFuncs.Color4ub( sf->fader, sf->fadeg, sf->fadeb, alpha );
}
ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1,
R_GetBuiltinTexture( REF_WHITE_TEXTURE ));
@@ -780,14 +777,14 @@ static const char *CL_SoundFromIndex( int index )
if( !hSound )
{
Con_DPrintf( S_ERROR "%s: invalid sound index %i\n", __func__, index );
Con_DPrintf( S_ERROR "CL_SoundFromIndex: invalid sound index %i\n", index );
return NULL;
}
sfx = S_GetSfxByHandle( hSound );
if( !sfx )
{
Con_DPrintf( S_ERROR "%s: bad sfx for index %i\n", __func__, index );
Con_DPrintf( S_ERROR "CL_SoundFromIndex: bad sfx for index %i\n", index );
return NULL;
}
@@ -1015,8 +1012,7 @@ void CL_DrawHUD( int state )
CL_DrawCrosshair ();
CL_DrawCenterPrint ();
clgame.dllFuncs.pfnRedraw( cl.time, cl.intermission );
if( showpause.value )
CL_DrawLoadingOrPaused( cls.pauseIcon );
CL_DrawLoadingOrPaused( cls.pauseIcon );
break;
case CL_LOADING:
CL_DrawLoadingOrPaused( cls.loadingBar );
@@ -1045,10 +1041,10 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize )
int i;
if( !pszName || !*pszName )
Host_Error( "%s: bad message name\n", __func__ );
Host_Error( "CL_LinkUserMessage: bad message name\n" );
if( svc_num <= svc_lastmsg )
Host_Error( "%s: tried to hook a system message \"%s\"\n", __func__, svc_strings[svc_num] );
Host_Error( "CL_LinkUserMessage: tried to hook a system message \"%s\"\n", svc_strings[svc_num] );
// see if already hooked
for( i = 0; i < MAX_USER_MESSAGES && clgame.msg[i].name[0]; i++ )
@@ -1065,7 +1061,7 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize )
if( i == MAX_USER_MESSAGES )
{
Host_Error( "%s: MAX_USER_MESSAGES hit!\n", __func__ );
Host_Error( "CL_LinkUserMessage: MAX_USER_MESSAGES hit!\n" );
return;
}
@@ -1186,7 +1182,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
if( type == SPR_CLIENT || type == SPR_HUDSPRITE )
SetBits( m_pSprite->flags, MODEL_CLIENT );
m_pSprite->numtexinfo = texFlags; // store texFlags for renderer into numtexinfo
m_pSprite->numtexinfo = texFlags; // store texFlags into numtexinfo
if( !FS_FileExists( szSpriteName, false ) )
{
@@ -1213,7 +1209,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
ref.dllFuncs.Mod_LoadMapSprite( m_pSprite, buf, size, &loaded );
else
{
Mod_LoadSpriteModel( m_pSprite, buf, &loaded );
Mod_LoadSpriteModel( m_pSprite, buf, &loaded, texFlags );
ref.dllFuncs.Mod_ProcessRenderData( m_pSprite, true, buf );
}
@@ -1246,7 +1242,7 @@ static model_t *CL_LoadSpriteModel( const char *filename, uint type, uint texFla
if( !COM_CheckString( filename ))
{
Con_Reportf( S_ERROR "%s: bad name!\n", __func__ );
Con_Reportf( S_ERROR "CL_LoadSpriteModel: bad name!\n" );
return NULL;
}
@@ -1452,7 +1448,7 @@ pfnSPR_Draw
*/
static void GAME_EXPORT pfnSPR_Draw( int frame, int x, int y, const wrect_t *prc )
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransAlpha );
ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
SPR_DrawGeneric( frame, x, y, -1, -1, prc );
}
@@ -1507,12 +1503,12 @@ static void GAME_EXPORT pfnSPR_DrawAdditive( int frame, int x, int y, const wrec
/*
=========
SPR_GetList
pfnSPR_GetList
for parsing half-life scripts - hud.txt etc
=========
*/
static client_sprite_t *SPR_GetList( char *psz, int *piCount )
static client_sprite_t *pfnSPR_GetList( char *psz, int *piCount )
{
cached_spritelist_t *pEntry = &clgame.sprlist[0];
int slot, index, numSprites = 0;
@@ -1538,7 +1534,7 @@ static client_sprite_t *SPR_GetList( char *psz, int *piCount )
if( slot == MAX_CLIENT_SPRITES )
{
Con_Printf( S_ERROR "%s: overflow cache!\n", __func__ );
Con_Printf( S_ERROR "SPR_GetList: overflow cache!\n" );
return NULL;
}
@@ -1717,8 +1713,7 @@ pfnCvar_RegisterVariable
static cvar_t *GAME_EXPORT pfnCvar_RegisterClientVariable( const char *szName, const char *szValue, int flags )
{
// a1ba: try to mitigate outdated client.dll vulnerabilities
if( !Q_stricmp( szName, "motdfile" )
|| !Q_stricmp( szName, "sensitivity" ))
if( !Q_stricmp( szName, "motdfile" ))
flags |= FCVAR_PRIVILEGED;
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_CLIENTDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_CLIENTDLL ));
@@ -1747,7 +1742,7 @@ static int GAME_EXPORT pfnHookUserMsg( const char *pszName, pfnUserMsgHook pfn )
if( i == MAX_USER_MESSAGES )
{
Host_Error( "%s: MAX_USER_MESSAGES hit!\n", __func__ );
Host_Error( "HookUserMsg: MAX_USER_MESSAGES hit!\n" );
return 0;
}
@@ -2297,7 +2292,7 @@ static void GAME_EXPORT pfnHookEvent( const char *filename, pfnEventHook pfn )
if( !Q_stricmp( name, ev->name ) && ev->func != NULL )
{
Con_Reportf( S_WARN "%s: %s already hooked!\n", __func__, name );
Con_Reportf( S_WARN "CL_HookEvent: %s already hooked!\n", name );
return;
}
}
@@ -2380,7 +2375,7 @@ static int GAME_EXPORT CL_FindModelIndex( const char *m )
if( lasttimewarn < host.realtime )
{
// tell user about problem (but don't spam console)
Con_DPrintf( S_ERROR "Could not find index for model %s: not precached\n", filepath );
Con_Printf( S_ERROR "Could not find index for model %s: not precached\n", filepath );
lasttimewarn = host.realtime + 1.0f;
}
@@ -2432,8 +2427,8 @@ static void GAME_EXPORT pfnLocalPlayerBounds( int hull, float *mins, float *maxs
{
if( hull >= 0 && hull < 4 )
{
if( mins ) VectorCopy( host.player_mins[hull], mins );
if( maxs ) VectorCopy( host.player_maxs[hull], maxs );
if( mins ) VectorCopy( clgame.pmove->player_mins[hull], mins );
if( maxs ) VectorCopy( clgame.pmove->player_maxs[hull], maxs );
}
}
@@ -2501,17 +2496,9 @@ CL_PushTraceBounds
*/
static void GAME_EXPORT CL_PushTraceBounds( int hullnum, const float *mins, const float *maxs )
{
if( !host.trace_bounds_pushed )
{
memcpy( host.player_mins_backup, host.player_mins, sizeof( host.player_mins_backup ));
memcpy( host.player_maxs_backup, host.player_maxs, sizeof( host.player_maxs_backup ));
host.trace_bounds_pushed = true;
}
hullnum = bound( 0, hullnum, 3 );
VectorCopy( mins, host.player_mins[hullnum] );
VectorCopy( maxs, host.player_maxs[hullnum] );
VectorCopy( mins, clgame.pmove->player_mins[hullnum] );
VectorCopy( maxs, clgame.pmove->player_maxs[hullnum] );
}
/*
@@ -2522,15 +2509,8 @@ CL_PopTraceBounds
*/
static void GAME_EXPORT CL_PopTraceBounds( void )
{
if( !host.trace_bounds_pushed )
{
Con_Reportf( S_ERROR "%s called without push!\n", __func__ );
return;
}
host.trace_bounds_pushed = false;
memcpy( host.player_mins, host.player_mins_backup, sizeof( host.player_mins ));
memcpy( host.player_maxs, host.player_maxs_backup, sizeof( host.player_maxs ));
memcpy( clgame.pmove->player_mins, host.player_mins, sizeof( host.player_mins ));
memcpy( clgame.pmove->player_maxs, host.player_maxs, sizeof( host.player_maxs ));
}
/*
@@ -2807,10 +2787,10 @@ static void GAME_EXPORT PlayerInfo_SetValueForKey( const char *key, const char *
{
Cvar_DirectSet( var, value );
}
else if( Info_SetValueForStarKey( cls.userinfo, key, value, sizeof( cls.userinfo )))
else if( Info_SetValueForStarKey( cls.userinfo, key, value, MAX_INFO_STRING ))
{
// time to update server copy of userinfo
CL_UpdateInfo( key, value );
CL_ServerCommand( true, "setinfo \"%s\" \"%s\"\n", key, value );
}
}
@@ -3302,7 +3282,7 @@ Heavy legacy of Quake...
*/
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode )
{
if( rendermode == kRenderTransAlpha )
if( clgame.ds.renderMode == kRenderTransAlpha )
{
clgame.ds.triRGBA[3] = a / 255.0f;
ref.dllFuncs.Color4f( r, g, b, a );
@@ -3434,15 +3414,16 @@ NetAPI_SendRequest
static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags, double timeout, netadr_t *remote_address, net_api_response_func_t response )
{
net_request_t *nr = NULL;
string req;
int i;
if( !response )
{
Con_DPrintf( S_ERROR "%s: no callbcak specified for request with context %i!\n", __func__, context );
Con_DPrintf( S_ERROR "Net_SendRequest: no callbcak specified for request with context %i!\n", context );
return;
}
if( remote_address->type == NA_IPX || remote_address->type == NA_BROADCAST_IPX )
if( remote_address->type != NA_IPX && remote_address->type != NA_BROADCAST_IPX )
return; // IPX no longer support
if( request == NETAPI_REQUEST_SERVERLIST )
@@ -3485,7 +3466,8 @@ static void GAME_EXPORT NetAPI_SendRequest( int context, int request, int flags,
nr->flags = flags;
// local servers request
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "netinfo %i %i %i", FBitSet( flags, FNETAPI_LEGACY_PROTOCOL ) ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION, context, request );
Q_snprintf( req, sizeof( req ), "netinfo %i %i %i", PROTOCOL_VERSION, context, request );
Netchan_OutOfBandPrint( NS_CLIENT, nr->resp.remote_address, "%s", req );
}
/*
@@ -3789,7 +3771,7 @@ static demo_api_t gDemoApi =
Demo_WriteBuffer,
};
net_api_t gNetApi =
static net_api_t gNetApi =
{
NetAPI_InitNetworking,
NetAPI_Status,
@@ -3825,7 +3807,7 @@ static cl_enginefunc_t gEngfuncs =
pfnSPR_DrawAdditive,
SPR_EnableScissor,
SPR_DisableScissor,
SPR_GetList,
pfnSPR_GetList,
CL_FillRGBA,
CL_GetScreenInfo,
pfnSetCrosshair,
@@ -4047,14 +4029,14 @@ qboolean CL_LoadProgs( const char *name )
// trying to get single export
if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "GetClientAPI" )) != NULL )
{
Con_Reportf( "%s: found single callback export\n", __func__ );
Con_Reportf( "CL_LoadProgs: found single callback export\n" );
// trying to fill interface now
GetClientAPI( &clgame.dllFuncs );
}
else if(( GetClientAPI = (void *)COM_GetProcAddress( clgame.hInstance, "F" )) != NULL )
{
Con_Reportf( "%s: found single callback export (secured client dlls)\n", __func__ );
Con_Reportf( "CL_LoadProgs: found single callback export (secured client dlls)\n" );
// trying to fill interface now
CL_GetSecuredClientAPI( GetClientAPI );
@@ -4082,7 +4064,7 @@ qboolean CL_LoadProgs( const char *name )
// functions are cleared before all the extensions are evaluated
if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL )
{
Con_Reportf( "%s: failed to get address of %s proc\n", __func__, func->name );
Con_Reportf( "CL_LoadProgs: failed to get address of %s proc\n", func->name );
if( critical_exports )
{
@@ -4109,13 +4091,13 @@ qboolean CL_LoadProgs( const char *name )
// functions are cleared before all the extensions are evaluated
// NOTE: new exports can be missed without stop the engine
if(( *func->func = (void *)COM_GetProcAddress( clgame.hInstance, func->name )) == NULL )
Con_Reportf( "%s: failed to get address of %s proc\n", __func__, func->name );
Con_Reportf( "CL_LoadProgs: failed to get address of %s proc\n", func->name );
}
if( !clgame.dllFuncs.pfnInitialize( &gEngfuncs, CLDLL_INTERFACE_VERSION ))
{
COM_FreeLibrary( clgame.hInstance );
Con_Reportf( "%s: can't init client API\n", __func__ );
Con_Reportf( "CL_LoadProgs: can't init client API\n" );
clgame.hInstance = NULL;
return false;
}
@@ -4132,10 +4114,10 @@ qboolean CL_LoadProgs( const char *name )
CL_InitTempEnts ();
if( !R_InitRenderAPI()) // Xash3D extension
Con_Reportf( S_WARN "%s: couldn't get render API\n", __func__ );
Con_Reportf( S_WARN "CL_LoadProgs: couldn't get render API\n" );
if( !Mobile_Init() ) // Xash3D FWGS extension: mobile interface
Con_Reportf( S_WARN "%s: couldn't get mobility API\n", __func__ );
Con_Reportf( S_WARN "CL_LoadProgs: couldn't get mobility API\n" );
CL_InitEdicts( cl.maxclients ); // initailize local player and world
CL_InitClientMove(); // initialize pm_shared

View File

@@ -25,14 +25,6 @@ static void UI_UpdateUserinfo( void );
gameui_static_t gameui;
static void UI_ToggleAllowConsole_f( void )
{
host.allow_console = host.allow_console_init = true;
if( gameui.globals )
gameui.globals->developer = true;
}
void UI_UpdateMenu( float realtime )
{
if( !gameui.hInstance ) return;
@@ -224,14 +216,12 @@ UI_ShowConnectionWarning
show message box
=================
*/
qboolean UI_ShowMessageBox( const char *text )
void UI_ShowMessageBox( const char *text )
{
if( gameui.dllFuncs2.pfnShowMessageBox )
{
gameui.dllFuncs2.pfnShowMessageBox( text );
return true;
}
return false;
}
void UI_ConnectionProgress_Disconnect( void )
@@ -407,21 +397,17 @@ void Host_Credits( void )
gameui.dllFuncs.pfnFinalCredits();
}
static void UI_ConvertGameInfo( gameinfo2_t *out, const gameinfo_t *in )
static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
{
out->gi_version = GAMEINFO_VERSION;
Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder ));
Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap ));
Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap ));
Q_strncpy( out->demomap, in->demomap, sizeof( out->demomap ));
Q_strncpy( out->title, in->title, sizeof( out->title ));
Q_snprintf( out->version, sizeof( out->version ), "%g", in->version );
Q_strncpy( out->iconpath, in->iconpath, sizeof( out->iconpath ));
Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url ));
Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url ));
out->size = in->size;
Q_strncpy( out->size, Q_pretifymem( in->size, 0 ), sizeof( out->size ));
Q_strncpy( out->type, in->type, sizeof( out->type ));
Q_strncpy( out->date, in->date, sizeof( out->date ));
@@ -439,31 +425,6 @@ static void UI_ConvertGameInfo( gameinfo2_t *out, const gameinfo_t *in )
SetBits( out->flags, GFL_ANIMATED_TITLE );
}
static void UI_ToOldGameInfo( GAMEINFO *out, const gameinfo2_t *in )
{
Q_strncpy( out->gamefolder, in->gamefolder, sizeof( out->gamefolder ));
Q_strncpy( out->startmap, in->startmap, sizeof( out->startmap ));
Q_strncpy( out->trainmap, in->trainmap, sizeof( out->trainmap ));
Q_strncpy( out->title, in->title, sizeof( out->title ));
Q_strncpy( out->version, in->version, sizeof( out->version ));
out->flags = in->flags & 0xFFFF;
Q_strncpy( out->game_url, in->game_url, sizeof( out->game_url ));
Q_strncpy( out->update_url, in->update_url, sizeof( out->update_url ));
Q_strncpy( out->size, Q_memprint( in->size ), sizeof( out->size ));
Q_strncpy( out->type, in->type, sizeof( out->type ));
Q_strncpy( out->date, in->date, sizeof( out->date ));
out->gamemode = in->gamemode;
}
static void UI_GetModsInfo( void )
{
int i;
gameui.modsInfo = Mem_Calloc( gameui.mempool, sizeof( *gameui.modsInfo ) * FI->numgames );
for( i = 0; i < FI->numgames; i++ )
UI_ConvertGameInfo( &gameui.modsInfo[i], FI->games[i] );
}
/*
====================
PIC_DrawGeneric
@@ -531,7 +492,7 @@ static HIMAGE GAME_EXPORT pfnPIC_Load( const char *szPicName, const byte *image_
if( !COM_CheckString( szPicName ))
{
Con_Reportf( S_ERROR "%s: refusing to load image with empty name\n", __func__ );
Con_Reportf( S_ERROR "CL_LoadImage: refusing to load image with empty name\n" );
return 0;
}
@@ -961,12 +922,11 @@ pfnGetGameInfo
=========
*/
static int GAME_EXPORT pfnGetOldGameInfo( GAMEINFO *pgameinfo )
static int GAME_EXPORT pfnGetGameInfo( GAMEINFO *pgameinfo )
{
if( !pgameinfo )
return 0;
if( !pgameinfo ) return 0;
UI_ToOldGameInfo( pgameinfo, &gameui.gameInfo );
*pgameinfo = gameui.gameInfo;
return 1;
}
@@ -978,26 +938,8 @@ pfnGetGamesList
*/
static GAMEINFO ** GAME_EXPORT pfnGetGamesList( int *numGames )
{
if( numGames )
*numGames = FI->numgames;
if( !gameui.oldModsInfo )
{
int i;
if( !gameui.modsInfo )
UI_GetModsInfo();
// first allocate array of pointers
gameui.oldModsInfo = Mem_Calloc( gameui.mempool, sizeof( *gameui.oldModsInfo ) * FI->numgames );
for( i = 0; i < FI->numgames; i++ )
{
gameui.oldModsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( *gameui.oldModsInfo[i] ));
UI_ToOldGameInfo( gameui.oldModsInfo[i], &gameui.modsInfo[i] );
}
}
return gameui.oldModsInfo;
if( numGames ) *numGames = FI->numgames;
return gameui.modsInfo;
}
/*
@@ -1069,7 +1011,7 @@ pfnChangeInstance
*/
static void GAME_EXPORT pfnChangeInstance( const char *newInstance, const char *szFinalMessage )
{
Con_Reportf( S_ERROR "%s menu call is deprecated!\n", __func__ );
Con_Reportf( S_ERROR "ChangeInstance menu call is deprecated!\n" );
}
/*
@@ -1155,22 +1097,8 @@ static void GAME_EXPORT pfnCon_DefaultColor( int r, int g, int b )
Con_DefaultColor( r, g, b, true );
}
static void GAME_EXPORT pfnSetCursor( void *hCursor )
{
uintptr_t cursor;
if( !gameui.use_extended_api )
return; // ignore original Xash menus
cursor = (uintptr_t)hCursor;
if( cursor < dc_user || cursor > dc_last )
return;
Platform_SetCursorType( cursor );
}
// engine callbacks
static const ui_enginefuncs_t gEngfuncs =
static ui_enginefuncs_t gEngfuncs =
{
pfnPIC_Load,
GL_FreeImage,
@@ -1234,7 +1162,7 @@ static const ui_enginefuncs_t gEngfuncs =
pfnKeyGetState,
pfnMemAlloc,
pfnMemFree,
pfnGetOldGameInfo,
pfnGetGameInfo,
pfnGetGamesList,
pfnGetFilesList,
SV_GetSaveComment,
@@ -1248,7 +1176,7 @@ static const ui_enginefuncs_t gEngfuncs =
pfnHostEndGame,
COM_RandomFloat,
COM_RandomLong,
pfnSetCursor,
IN_SetCursor,
pfnIsMapValid,
GL_ProcessTexture,
COM_CompareFileTime,
@@ -1281,28 +1209,6 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
}
static gameinfo2_t *pfnGetGameInfo( int gi_version )
{
if( gi_version != gameui.gameInfo.gi_version )
return NULL;
return &gameui.gameInfo;
}
static gameinfo2_t *pfnGetModInfo( int gi_version, int i )
{
if( i < 0 || i >= FI->numgames )
return NULL;
if( !gameui.modsInfo )
UI_GetModsInfo();
if( gi_version != gameui.modsInfo[i].gi_version )
return NULL;
return &gameui.modsInfo[i];
}
static ui_extendedfuncs_t gExtendedfuncs =
{
pfnEnableTextInput,
@@ -1315,9 +1221,6 @@ static ui_extendedfuncs_t gExtendedfuncs =
NET_AdrToString,
NET_CompareAdrSort,
Sys_GetNativeObject,
&gNetApi,
pfnGetGameInfo,
pfnGetModInfo,
};
void UI_UnloadProgs( void )
@@ -1327,7 +1230,6 @@ void UI_UnloadProgs( void )
// deinitialize game
gameui.dllFuncs.pfnShutdown();
Cmd_RemoveCommand( "ui_allowconsole" );
Cvar_FullSet( "host_gameuiloaded", "0", FCVAR_READ_ONLY );
Cvar_Unlink( FCVAR_GAMEUIDLL );
@@ -1378,65 +1280,71 @@ qboolean UI_LoadProgs( void )
if(( GetMenuAPI = (MENUAPI)COM_GetProcAddress( gameui.hInstance, "GetMenuAPI" )) == NULL )
{
COM_FreeLibrary( gameui.hInstance );
Con_Reportf( "%s: can't init menu API\n", __func__ );
Con_Reportf( "UI_LoadProgs: can't init menu API\n" );
gameui.hInstance = NULL;
return false;
}
gameui.use_extended_api = false;
gameui.use_text_api = false;
// make local copy of engfuncs to prevent overwrite it with user dll
gpEngfuncs = gEngfuncs;
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
gameui.mempool = Mem_AllocPool( "Menu Pool" );
if( !GetMenuAPI( &gameui.dllFuncs, &gpEngfuncs, gameui.globals ))
{
COM_FreeLibrary( gameui.hInstance );
Con_Reportf( "%s: can't init menu API\n", __func__ );
Con_Reportf( "UI_LoadProgs: can't init menu API\n" );
Mem_FreePool( &gameui.mempool );
gameui.hInstance = NULL;
return false;
}
// make local copy of engfuncs to prevent overwrite it with user dll
gpExtendedfuncs = gExtendedfuncs;
memcpy( &gpExtendedfuncs, &gExtendedfuncs, sizeof( gExtendedfuncs ));
memset( &gameui.dllFuncs2, 0, sizeof( gameui.dllFuncs2 ));
// try to initialize new extended API
if( ( GetExtAPI = (UIEXTENEDEDAPI)COM_GetProcAddress( gameui.hInstance, "GetExtAPI" ) ) )
{
Con_Reportf( "%s: extended Menu API found\n", __func__ );
Con_Reportf( "UI_LoadProgs: extended Menu API found\n" );
if( GetExtAPI( MENU_EXTENDED_API_VERSION, &gameui.dllFuncs2, &gpExtendedfuncs ) )
{
Con_Reportf( "%s: extended Menu API initialized\n", __func__ );
gameui.use_extended_api = true;
Con_Reportf( "UI_LoadProgs: extended Menu API initialized\n" );
gameui.use_text_api = true;
}
}
else // otherwise, fallback to old and deprecated extensions
{
if( ( GiveTextApi = (UITEXTAPI)COM_GetProcAddress( gameui.hInstance, "GiveTextAPI" ) ) )
{
Con_Reportf( "%s: extended text API found\n", __func__ );
Con_Reportf( "UI_LoadProgs: extended text API found\n" );
Con_Reportf( S_WARN "Text API is deprecated! If you are mod developer, consider moving to Extended Menu API!\n" );
if( GiveTextApi( &gpExtendedfuncs ) ) // they are binary compatible, so we can just pass extended funcs API to menu
{
Con_Reportf( "%s: extended text API initialized\n", __func__ );
gameui.use_extended_api = true;
Con_Reportf( "UI_LoadProgs: extended text API initialized\n" );
gameui.use_text_api = true;
}
}
gameui.dllFuncs2.pfnAddTouchButtonToList = (ADDTOUCHBUTTONTOLIST)COM_GetProcAddress( gameui.hInstance, "AddTouchButtonToList" );
if( gameui.dllFuncs2.pfnAddTouchButtonToList )
{
Con_Reportf( "%s: AddTouchButtonToList call found\n", __func__ );
Con_Reportf( "UI_LoadProgs: AddTouchButtonToList call found\n" );
Con_Reportf( S_WARN "AddTouchButtonToList is deprecated! If you are mod developer, consider moving to Extended Menu API!\n" );
}
}
Cvar_FullSet( "host_gameuiloaded", "1", FCVAR_READ_ONLY );
Cmd_AddRestrictedCommand( "ui_allowconsole", UI_ToggleAllowConsole_f, "unlocks developer console" );
// setup gameinfo
for( i = 0; i < FI->numgames; i++ )
{
gameui.modsInfo[i] = Mem_Calloc( gameui.mempool, sizeof( GAMEINFO ));
UI_ConvertGameInfo( gameui.modsInfo[i], FI->games[i] );
}
UI_ConvertGameInfo( &gameui.gameInfo, FI->GameInfo ); // current gameinfo

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,8 @@ GNU General Public License for more details.
#include "input.h"
#include "platform/platform.h"
static mobile_engfuncs_t *gMobileEngfuncs;
static CVAR_DEFINE_AUTO( vibration_length, "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "vibration length" );
static CVAR_DEFINE_AUTO( vibration_enable, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "enable vibration" );
@@ -28,9 +30,17 @@ static float g_font_scale;
static void pfnVibrate( float life, char flags )
{
if( !vibration_enable.value || life < 0.0f )
if( !vibration_enable.value )
return;
if( life < 0.0f )
{
Con_Reportf( S_WARN "Negative vibrate time: %f\n", life );
return;
}
//Con_Reportf( "Vibrate: %f %d\n", life, flags );
// here goes platform-specific backends
Platform_Vibrate( life * vibration_length.value, flags );
}
@@ -43,7 +53,7 @@ static void Vibrate_f( void )
return;
}
pfnVibrate( Q_atof( Cmd_Argv( 1 )), VIBRATE_NORMAL );
pfnVibrate( Q_atof( Cmd_Argv(1) ), VIBRATE_NORMAL );
}
static void pfnEnableTextInput( int enable )
@@ -92,7 +102,7 @@ static char *pfnParseFileSafe( char *data, char *buf, const int size, unsigned i
return COM_ParseFileSafe( data, buf, size, flags, len, NULL );
}
static const mobile_engfuncs_t gMobileEngfuncs =
static mobile_engfuncs_t gpMobileEngfuncs =
{
MOBILITY_API_VERSION,
pfnVibrate,
@@ -112,38 +122,21 @@ static const mobile_engfuncs_t gMobileEngfuncs =
qboolean Mobile_Init( void )
{
qboolean success = false;
pfnMobilityInterface ExportToClient;
Cmd_AddCommand( "vibrate", Vibrate_f, "Vibrate for specified time");
// find a mobility interface
ExportToClient = COM_GetProcAddress( clgame.hInstance, MOBILITY_CLIENT_EXPORT );
gMobileEngfuncs = &gpMobileEngfuncs;
if( ExportToClient && !ExportToClient( gMobileEngfuncs ) )
success = true;
Cmd_AddCommand( "vibrate", (xcommand_t)Vibrate_f, "Vibrate for specified time");
Cvar_RegisterVariable( &vibration_length );
Cvar_RegisterVariable( &vibration_enable );
// find mobility interface
if(( ExportToClient = COM_GetProcAddress( clgame.hInstance, MOBILITY_CLIENT_EXPORT )))
{
static mobile_engfuncs_t mobile_engfuncs; // keep a copy, don't let user change engine pointers
mobile_engfuncs = gMobileEngfuncs;
if( !ExportToClient( &mobile_engfuncs ))
{
Con_Reportf( "%s: ^2initailized extended MobilityAPI ^7ver. %i\n", __func__, MOBILITY_API_VERSION );
return true;
}
// make sure that mobile functions are cleared
#if 1
// some SDKs define export as returning void, breaking the contract
// ignore result for now...
return true;
#else
memset( &mobile_engfuncs, 0, sizeof( mobile_engfuncs ));
return false; // just tell user about problems
#endif
}
return true; // mobile interface is missed
return success;
}
void Mobile_Shutdown( void )

View File

@@ -63,9 +63,9 @@ static byte netcolors[NETGRAPH_NET_COLORS+NETGRAPH_LERP_HEIGHT][4] =
// other will be generated through NetGraph_InitColors()
};
static const byte sendcolor[4] = { 88, 29, 130, 255 };
static const byte holdcolor[4] = { 255, 0, 0, 200 };
static const byte extrap_base_color[4] = { 255, 255, 255, 255 };
static byte sendcolor[4] = { 88, 29, 130, 255 };
static byte holdcolor[4] = { 255, 0, 0, 200 };
static byte extrap_base_color[4] = { 255, 255, 255, 255 };
static netbandwidthgraph_t netstat_graph[NET_TIMINGS];
static float packet_loss;
static float packet_choke;
@@ -79,7 +79,7 @@ NetGraph_DrawRect
NetGraph_FillRGBA shortcut
==========
*/
static void NetGraph_DrawRect( const wrect_t *rect, const byte colors[4] )
static void NetGraph_DrawRect( wrect_t *rect, byte colors[4] )
{
ref.dllFuncs.Color4ub( colors[0], colors[1], colors[2], colors[3] ); // color for this quad

File diff suppressed because it is too large Load Diff

View File

@@ -137,7 +137,12 @@ static void CL_LegacyParseSoundPacket( sizebuf_t *msg, qboolean is_ambient )
if( FBitSet( flags, SND_SENTENCE ))
{
char sentenceName[32];
//if( FBitSet( flags, SND_SEQUENCE ))
//Q_snprintf( sentenceName, sizeof( sentenceName ), "!#%i", sound + MAX_SOUNDS );
//else
Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
handle = S_RegisterSound( sentenceName );
}
else handle = cl.sound_index[sound]; // see precached sound
@@ -169,7 +174,7 @@ static void CL_LegacyPrecacheSound( sizebuf_t *msg )
soundIndex = MSG_ReadUBitLong( msg, MAX_SOUND_BITS );
if( soundIndex < 0 || soundIndex >= MAX_SOUNDS )
Host_Error( "%s: bad soundindex %i\n", __func__, soundIndex );
Host_Error( "CL_PrecacheSound: bad soundindex %i\n", soundIndex );
Q_strncpy( cl.sound_precache[soundIndex], MSG_ReadString( msg ), sizeof( cl.sound_precache[0] ));
@@ -187,9 +192,9 @@ static void CL_LegacyPrecacheModel( sizebuf_t *msg )
modelIndex = MSG_ReadUBitLong( msg, MAX_LEGACY_MODEL_BITS );
if( modelIndex < 0 || modelIndex >= MAX_MODELS )
Host_Error( "%s: bad modelindex %i\n", __func__, modelIndex );
Host_Error( "CL_PrecacheModel: bad modelindex %i\n", modelIndex );
Q_strncpy( model, MSG_ReadString( msg ), sizeof( model ));
Q_strncpy( model, MSG_ReadString( msg ), MAX_STRING );
//Q_strncpy( cl.model_precache[modelIndex], BF_ReadString( msg ), sizeof( cl.model_precache[0] ));
// when we loading map all resources is precached sequentially
@@ -216,7 +221,7 @@ static void CL_LegacyPrecacheEvent( sizebuf_t *msg )
eventIndex = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
if( eventIndex < 0 || eventIndex >= MAX_EVENTS )
Host_Error( "%s: bad eventindex %i\n", __func__, eventIndex );
Host_Error( "CL_PrecacheEvent: bad eventindex %i\n", eventIndex );
Q_strncpy( cl.event_precache[eventIndex], MSG_ReadString( msg ), sizeof( cl.event_precache[0] ));
@@ -251,15 +256,15 @@ static void CL_LegacyParseResourceList( sizebuf_t *msg )
reslist.rescount = MSG_ReadWord( msg ) - 1;
if( reslist.rescount > MAX_LEGACY_RESOURCES )
Host_Error( "MAX_RESOURCES reached\n" );
Host_Error("MAX_RESOURCES reached\n");
for( i = 0; i < reslist.rescount; i++ )
{
reslist.restype[i] = MSG_ReadWord( msg );
Q_strncpy( reslist.resnames[i], MSG_ReadString( msg ), sizeof( reslist.resnames[i] ));
Q_strncpy( reslist.resnames[i], MSG_ReadString( msg ), MAX_QPATH );
}
if( cls.demoplayback )
if( CL_IsPlaybackDemo() )
return;
if( !cl_allow_download.value )
@@ -312,19 +317,36 @@ CL_ParseLegacyServerMessage
dispatch messages
=====================
*/
void CL_ParseLegacyServerMessage( sizebuf_t *msg )
void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
{
size_t bufStart, playerbytes;
int cmd;
int cmd, param1, param2;
int old_background;
const char *s;
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
CL_Parse_Debug( true ); // begin parsing
if( normal_message )
{
// assume no entity/player update this packet
if( cls.state == ca_active )
{
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
}
else
{
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
}
}
// parse the message
while( 1 )
{
if( MSG_CheckOverflow( msg ))
{
Host_Error( "%s: overflow!\n", __func__ );
Host_Error( "CL_ParseServerMessage: overflow!\n" );
return;
}
@@ -340,9 +362,6 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonDLLMessage( msg, PROTO_LEGACY, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
@@ -357,7 +376,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
Host_AbortCurrentFrame ();
break;
case svc_legacy_event:
CL_ParseEvent( msg, PROTO_LEGACY );
CL_ParseEvent( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_legacy_changing:
@@ -366,9 +385,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
{
int maxclients = cl.maxclients;
// we can only changelevel in singleplayer
// and singleplayer always runs in current protocol
// cls.changelevel = true;
cls.changelevel = true;
S_StopAllSounds( true );
Con_Printf( "Server changing, reconnecting\n" );
@@ -419,7 +436,7 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
break;
case svc_time:
CL_ParseServerTime( msg, PROTO_LEGACY );
CL_ParseServerTime( msg );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
@@ -444,19 +461,19 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
break;
case svc_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, PROTO_LEGACY );
CL_ParseServerData( msg, true );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg, PROTO_LEGACY );
CL_ParseLightStyle( msg );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, PROTO_LEGACY );
CL_UpdateUserinfo( msg, true );
break;
case svc_deltatable:
Delta_ParseTableField( msg );
break;
case svc_clientdata:
CL_ParseClientData( msg, PROTO_LEGACY );
CL_ParseClientData( msg );
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resource:
@@ -466,58 +483,82 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
CL_UpdateUserPings( msg );
break;
case svc_particle:
CL_ParseParticles( msg, PROTO_LEGACY );
CL_ParseParticles( msg );
break;
case svc_restoresound:
Con_Printf( S_ERROR "%s: svc_restoresound: implement me!\n", __func__ );
CL_ParseRestoreSoundPacket( msg );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnstatic:
CL_LegacyParseStaticEntity( msg );
break;
case svc_event_reliable:
CL_ParseReliableEvent( msg, PROTO_LEGACY );
CL_ParseReliableEvent( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
CL_ParseBaseline( msg, PROTO_LEGACY );
CL_ParseBaseline( msg, true );
break;
case svc_temp_entity:
CL_ParseTempEntity( msg );
cl.frames[cl.parsecountmod].graphdata.tentities += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_setpause:
cl.paused = ( MSG_ReadOneBit( msg ) != 0 );
break;
case svc_signonnum:
CL_ParseSignon( msg, PROTO_LEGACY );
CL_ParseSignon( msg );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_intermission:
cl.intermission = 1;
break;
case svc_legacy_modelindex:
CL_LegacyPrecacheModel( msg );
break;
case svc_legacy_soundindex:
CL_LegacyPrecacheSound( msg );
break;
case svc_cdtrack:
param1 = MSG_ReadByte( msg );
param1 = bound( 1, param1, MAX_CDTRACKS ); // tracknum
param2 = MSG_ReadByte( msg );
param2 = bound( 1, param2, MAX_CDTRACKS ); // loopnum
S_StartBackgroundTrack( clgame.cdtracks[param1-1], clgame.cdtracks[param2-1], 0, false );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_legacy_eventindex:
CL_LegacyPrecacheEvent(msg);
break;
case svc_weaponanim:
param1 = MSG_ReadByte( msg ); // iAnim
param2 = MSG_ReadByte( msg ); // body
CL_WeaponAnim( param1, param2 );
break;
case svc_bspdecal:
CL_ParseStaticDecal( msg );
break;
case svc_roomtype:
param1 = MSG_ReadShort( msg );
Cvar_SetValue( "room_type", param1 );
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_usermessage:
CL_RegisterUserMessage( msg, PROTO_LEGACY );
CL_RegisterUserMessage( msg );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntities( msg, false, PROTO_LEGACY );
playerbytes = CL_ParsePacketEntities( msg, false );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_deltapacketentities:
playerbytes = CL_ParsePacketEntities( msg, true, PROTO_LEGACY );
playerbytes = CL_ParsePacketEntities( msg, true );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
@@ -564,21 +605,41 @@ void CL_ParseLegacyServerMessage( sizebuf_t *msg )
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_director:
CL_ParseDirector( msg );
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_querycvarvalue:
CL_ParseCvarValue( msg, false, PROTO_LEGACY );
CL_ParseCvarValue( msg, false );
break;
case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true, PROTO_LEGACY );
CL_ParseCvarValue( msg, true );
break;
default:
CL_ParseUserMessage( msg, cmd, PROTO_LEGACY );
CL_ParseUserMessage( msg, cmd );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
break;
}
}
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
CL_Parse_Debug( false ); // done
// we don't know if it is ok to save a demo message until
// after we have parsed the frame
if( !cls.demoplayback )
{
if( cls.demorecording && !cls.demowaiting )
{
CL_WriteDemoMessage( false, cls.starting_count, msg );
}
else if( cls.state != ca_active )
{
CL_WriteDemoMessage( true, cls.starting_count, msg );
}
}
}
void CL_LegacyPrecache_f( void )
@@ -586,7 +647,7 @@ void CL_LegacyPrecache_f( void )
int spawncount, i;
model_t *mod;
if( cls.legacymode != PROTO_LEGACY )
if( !cls.legacymode )
return;
spawncount = Q_atoi( Cmd_Argv( 1 ));
@@ -603,9 +664,6 @@ void CL_LegacyPrecache_f( void )
if( clgame.entities )
clgame.entities->model = cl.worldmodel;
// load skybox
R_SetupSky( clgame.movevars.skyName );
// tell rendering system we have a new set of models.
ref.dllFuncs.R_NewMap ();
@@ -627,5 +685,22 @@ void CL_LegacyPrecache_f( void )
// Include server count in case server disconnects and changes level during d/l
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
cls.signon = SIGNONS - 1;
cls.signon = SIGNONS;
}
void CL_LegacyUpdateInfo( void )
{
if( !cls.legacymode )
return;
if( cls.state != ca_active )
return;
MSG_BeginClientCmd( &cls.netchan.message, clc_legacy_userinfo );
MSG_WriteString( &cls.netchan.message, cls.userinfo );
}
qboolean CL_LegacyMode( void )
{
return cls.legacymode;
}

View File

@@ -1,762 +0,0 @@
/*
cl_parse.c - parse a message received from the server (GoldSrc 48 protocol)
Copyright (C) 2008 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "common.h"
#include "client.h"
#include "net_encode.h"
#include "particledef.h"
#include "cl_tent.h"
#include "shake.h"
#include "hltv.h"
#include "input.h"
#include "server.h"
static void CL_ParseExtraInfo( sizebuf_t *msg )
{
string clientfallback;
Q_strncpy( clientfallback, MSG_ReadString( msg ), sizeof( clientfallback ));
if( COM_CheckStringEmpty( clientfallback ))
Con_Reportf( S_ERROR "%s: TODO: add fallback directory %s!\n", __func__ );
if( MSG_ReadByte( msg ))
{
Cvar_FullSet( "sv_cheats", "1", FCVAR_READ_ONLY | FCVAR_SERVER );
}
else
{
Cvar_SetCheatState();
Cvar_FullSet( "sv_cheats", "0", FCVAR_READ_ONLY | FCVAR_SERVER );
}
}
static void CL_ParseNewMovevars( sizebuf_t *msg )
{
Delta_InitClient(); // finalize client delta's
clgame.movevars.gravity = MSG_ReadFloat( msg );
clgame.movevars.stopspeed = MSG_ReadFloat( msg );
clgame.movevars.maxspeed = MSG_ReadFloat( msg );
clgame.movevars.spectatormaxspeed = MSG_ReadFloat( msg );
clgame.movevars.accelerate = MSG_ReadFloat( msg );
clgame.movevars.airaccelerate = MSG_ReadFloat( msg );
clgame.movevars.wateraccelerate = MSG_ReadFloat( msg );
clgame.movevars.friction = MSG_ReadFloat( msg );
clgame.movevars.edgefriction = MSG_ReadFloat( msg );
clgame.movevars.waterfriction = MSG_ReadFloat( msg );
clgame.movevars.entgravity = MSG_ReadFloat( msg );
clgame.movevars.bounce = MSG_ReadFloat( msg );
clgame.movevars.stepsize = MSG_ReadFloat( msg );
clgame.movevars.maxvelocity = MSG_ReadFloat( msg );
clgame.movevars.zmax = MSG_ReadFloat( msg );
clgame.movevars.waveHeight = MSG_ReadFloat( msg );
clgame.movevars.footsteps = MSG_ReadByte( msg );
clgame.movevars.rollangle = MSG_ReadFloat( msg );
clgame.movevars.rollspeed = MSG_ReadFloat( msg );
clgame.movevars.skycolor_r = MSG_ReadFloat( msg );
clgame.movevars.skycolor_g = MSG_ReadFloat( msg );
clgame.movevars.skycolor_b = MSG_ReadFloat( msg );
clgame.movevars.skyvec_x = MSG_ReadFloat( msg );
clgame.movevars.skyvec_y = MSG_ReadFloat( msg );
clgame.movevars.skyvec_z = MSG_ReadFloat( msg );
Q_strncpy( clgame.movevars.skyName, MSG_ReadString( msg ), sizeof( clgame.movevars.skyName ));
// water alpha is not allowed
if( !FBitSet( world.flags, FWORLD_WATERALPHA ))
clgame.movevars.wateralpha = 1.0f;
// update sky if changed
if( Q_strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped )
R_SetupSky( clgame.movevars.skyName );
clgame.oldmovevars = clgame.movevars;
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
// keep features an actual!
clgame.oldmovevars.features = clgame.movevars.features = host.features;
}
typedef struct delta_header_t
{
qboolean remove : 1;
qboolean custom : 1;
qboolean instanced : 1;
uint instanced_baseline_index : 6;
uint offset : 6;
} delta_header_t;
static int CL_ParseDeltaHeader( sizebuf_t *msg, qboolean delta, int oldnum, struct delta_header_t *hdr )
{
int entnum = oldnum;
memset( hdr, 0, sizeof( *hdr ));
if( !delta )
{
// if we have one bit set, then it's a next entity in line
// if we have next bit NON set, then it's a one of next 64 entities
// if not, it's a new entity
if( MSG_ReadOneBit( msg ))
entnum++;
else if( MSG_ReadOneBit( msg ) == 0 )
entnum += MSG_ReadUBitLong( msg, 6 );
else
entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
}
else
{
// does this packet encode entity deletion?
hdr->remove = MSG_ReadOneBit( msg );
// same logic as above
if( MSG_ReadOneBit( msg ) == 0 )
entnum += MSG_ReadUBitLong( msg, 6 );
else entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
}
// if we are not removing this entity
if( !hdr->remove )
{
hdr->custom = MSG_ReadOneBit( msg );
// do we got instanced baselines in svc_spawnbaselines?
if( cl.instanced_baseline_count )
{
hdr->instanced = MSG_ReadOneBit( msg );
if( hdr->instanced )
hdr->instanced_baseline_index = MSG_ReadUBitLong( msg, 6 );
}
if( !delta && !hdr->instanced )
{
if( MSG_ReadOneBit( msg ))
hdr->offset = MSG_ReadUBitLong( msg, 6 );
}
}
return entnum;
}
static int CL_GetEntityDelta( const struct delta_header_t *hdr, int entnum )
{
if( hdr->custom )
return DT_CUSTOM_ENTITY_STATE_T;
if( CL_IsPlayerIndex( entnum ))
return DT_ENTITY_STATE_PLAYER_T;
return DT_ENTITY_STATE_T;
}
static void CL_FlushEntityPacketGS( frame_t *frame, sizebuf_t *msg )
{
frame->valid = false;
cl.validsequence = 0; // can't render a frame
// read it all but ignore it
while( 1 )
{
int num = 0;
entity_state_t from = { 0 }, to;
delta_header_t hdr;
if( MSG_ReadWord( msg ) != 0 )
{
MSG_SeekToBit( msg, -16, SEEK_CUR );
num = CL_ParseDeltaHeader( msg, false, num, &hdr );
}
else break;
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
if( hdr.remove )
continue;
Delta_ReadGSFields( msg, CL_GetEntityDelta( &hdr, num ), &from, &to, cl.mtime[0] );
}
}
static void CL_DeltaEntityGS( const delta_header_t *hdr, sizebuf_t *msg, frame_t *frame, int newnum, const entity_state_t *from )
{
cl_entity_t *ent;
entity_state_t *to;
qboolean newent = from == NULL;
int pack = frame->num_entities;
qboolean has_update = msg != NULL;
// alloc next slot to store update
to = &cls.packet_entities[cls.next_client_entities % cls.num_client_entities];
if(( newnum < 0 ) || ( newnum >= clgame.maxEntities ))
{
Con_DPrintf( S_ERROR "CL_DeltaEntity: invalid newnum: %d\n", newnum );
Host_Error( "%s: bad delta entity number: %i", __func__, newnum );
return;
}
ent = CL_EDICT_NUM( newnum );
if( hdr->remove )
{
if( !newent )
CL_KillDeadBeams( ent );
else
Con_Printf( S_WARN "%s: entity remove on non-delta update (%d)\n", __func__, newnum );
return;
}
ent->index = newnum; // enumerate entity index
if( newent )
{
if( hdr->instanced )
from = &cl.instanced_baseline[hdr->instanced_baseline_index];
else if( hdr->offset != 0 )
from = &cls.packet_entities[(cls.next_client_entities - hdr->offset) % cls.num_client_entities];
else
from = &ent->baseline;
}
if( has_update )
Delta_ReadGSFields( msg, CL_GetEntityDelta( hdr, newnum ), from, to, cl.mtime[0] );
else memcpy( to, from, sizeof( entity_state_t ));
to->entityType = hdr->custom ? ENTITY_BEAM : ENTITY_NORMAL;
to->number = newnum;
if( newent )
{
// interpolation must be reset
SETVISBIT( frame->flags, pack );
// release beams from previous entity
CL_KillDeadBeams( ent );
}
// add entity to packet
cls.next_client_entities++;
frame->num_entities++;
}
static void CL_CopyPacketEntity( frame_t *frame, int num, const entity_state_t *from )
{
delta_header_t fakehdr =
{
.custom = FBitSet( from->entityType, ENTITY_BEAM ) == ENTITY_BEAM,
};
CL_DeltaEntityGS( &fakehdr, NULL, frame, num, from );
}
static int CL_ParsePacketEntitiesGS( sizebuf_t *msg, qboolean delta )
{
frame_t *frame, *oldframe;
int oldindex, newnum, oldnum, numbase = 0;
entity_state_t *oldent;
int count;
int playerbytes = 0;
// save first uncompressed packet as timestamp
if( cls.changelevel && !delta && cls.demorecording )
CL_WriteDemoJumpTime();
count = MSG_ReadWord( msg );
frame = &cl.frames[cl.parsecountmod];
memset( frame->flags, 0, sizeof( frame->flags ));
frame->first_entity = cls.next_client_entities;
frame->num_entities = 0;
frame->valid = true;
if( delta )
{
uint oldpacket = MSG_ReadByte( msg );
oldframe = &cl.frames[oldpacket & CL_UPDATE_MASK];
if( !CL_ValidateDeltaPacket( oldpacket, oldframe ))
{
MSG_StartBitWriting( msg );
CL_FlushEntityPacketGS( frame, msg );
MSG_EndBitWriting( msg );
return playerbytes;
}
}
else
{
oldframe = NULL;
cl.send_reply = true;
cls.demowaiting = false;
}
cl.validsequence = cls.netchan.incoming_sequence;
MSG_StartBitWriting( msg );
oldent = NULL;
oldindex = 0;
oldnum = CL_UpdateOldEntNum( oldindex, oldframe, &oldent );
// read it all but ignore it
while( 1 )
{
int bufstart;
qboolean player;
delta_header_t hdr;
int val = MSG_ReadWord( msg );
if( val )
{
MSG_SeekToBit( msg, -16, SEEK_CUR );
numbase = newnum = CL_ParseDeltaHeader( msg, delta, numbase, &hdr );
}
else break;
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
player = CL_IsPlayerIndex( newnum );
while( oldnum < newnum )
{
if( !delta )
Con_Printf( S_WARN "%s: old frame copy on non-delta update (%d < %d)\n", __func__, oldnum, newnum );
// one or more entities from the old packet are unchanged
CL_CopyPacketEntity( frame, oldnum, oldent );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
bufstart = MSG_GetNumBytesRead( msg );
if( oldnum == newnum )
{
if( !delta )
Con_Printf( S_WARN "%s: delta entity on non-delta update (%d)\n", __func__, oldnum );
// from delta
CL_DeltaEntityGS( &hdr, msg, frame, newnum, oldent );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
else if( oldnum > newnum )
{
// from baseline
CL_DeltaEntityGS( &hdr, msg, frame, newnum, NULL );
}
if( player ) playerbytes += MSG_GetNumBytesRead( msg ) - bufstart;
}
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
// any remaining entities in the old frame are copied over
while( oldnum != MAX_ENTNUMBER )
{
// one or more entities from the old packet are unchanged
CL_CopyPacketEntity( frame, oldnum, oldent );
oldnum = CL_UpdateOldEntNum( ++oldindex, oldframe, &oldent );
}
MSG_EndBitWriting( msg );
if( frame->num_entities != count )
Con_Reportf( S_WARN "CL_Parse%sPacketEntitiesGS: (%i should be %i)\n", delta ? "Delta" : "", frame->num_entities, count );
if( !frame->valid )
return playerbytes;
CL_ProcessPacket( frame );
CL_SetSolidEntities();
// first update, received world, remove loading plaque
if( cls.signon == ( SIGNONS - 1 ))
{
cls.signon = SIGNONS;
CL_SignonReply( PROTO_GOLDSRC );
}
return playerbytes;
}
static float MSG_ReadGSBitCoord( sizebuf_t *sb )
{
float value = 0;
int ival, fval;
ival = MSG_ReadOneBit( sb );
fval = MSG_ReadOneBit( sb );
if( ival || fval )
{
int sign = MSG_ReadOneBit( sb );
if( ival )
ival = MSG_ReadUBitLong( sb, 12 );
if( fval )
fval = MSG_ReadUBitLong( sb, 3 );
value = (float)( fval / 8.0 + ival );
if( sign )
value = -value;
}
return value;
}
static void MSG_ReadGSBitVec3Coord( sizebuf_t *sb, vec3_t fa )
{
qboolean x, y, z;
VectorClear( fa );
x = MSG_ReadOneBit( sb );
y = MSG_ReadOneBit( sb );
z = MSG_ReadOneBit( sb );
if( x )
fa[0] = MSG_ReadGSBitCoord( sb );
if( y )
fa[1] = MSG_ReadGSBitCoord( sb );
if( z )
fa[2] = MSG_ReadGSBitCoord( sb );
}
static void CL_ParseSoundPacketGS( sizebuf_t *msg )
{
vec3_t pos;
int chan, sound;
float volume, attn;
int flags, pitch, entnum;
sound_t handle = 0;
MSG_StartBitWriting( msg );
flags = MSG_ReadUBitLong( msg, 9 );
if( FBitSet( flags, SND_VOLUME ))
volume = (float)MSG_ReadByte( msg ) / 255.0f;
else volume = VOL_NORM;
if( FBitSet( flags, SND_ATTENUATION ))
attn = (float)MSG_ReadByte( msg ) / 64.0f;
else attn = ATTN_NONE;
chan = MSG_ReadUBitLong( msg, 3 );
entnum = MSG_ReadUBitLong( msg, MAX_GOLDSRC_ENTITY_BITS );
if( FBitSet( flags, SND_LEGACY_LARGE_INDEX ))
sound = MSG_ReadWord( msg );
else sound = MSG_ReadByte( msg );
MSG_ReadGSBitVec3Coord( msg, pos );
if( FBitSet( flags, SND_PITCH ))
pitch = MSG_ReadByte( msg );
else pitch = PITCH_NORM;
MSG_EndBitWriting( msg );
ClearBits( flags, SND_LEGACY_LARGE_INDEX );
if( FBitSet( flags, SND_SENTENCE ))
{
char sentenceName[32];
Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
handle = S_RegisterSound( sentenceName );
}
else handle = cl.sound_index[sound]; // see precached sound
if( !cl.audio_prepped )
return; // too early
// g-cont. sound and ambient sound have only difference with channel
if( chan == CHAN_STATIC )
{
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
}
else
{
S_StartSound( pos, entnum, chan, handle, volume, attn, pitch, flags );
}
}
static void CL_ParseSpawnStaticSound( sizebuf_t *msg )
{
vec3_t pos;
int handle, entnum, pitch, flags;
float volume, attn;
MSG_ReadVec3Coord( msg, pos );
handle = MSG_ReadShort( msg );
volume = MSG_ReadByte( msg ) * ( 1.0f / 255.0f );
attn = MSG_ReadByte( msg ) * ( 1.0f / 64.0f );
entnum = MSG_ReadShort( msg );
pitch = MSG_ReadByte( msg );
flags = MSG_ReadByte( msg );
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
}
/*
=====================================================================
ACTION MESSAGES
=====================================================================
*/
/*
=====================
CL_ParseGoldSrcServerMessage
dispatch messages
=====================
*/
void CL_ParseGoldSrcServerMessage( sizebuf_t *msg )
{
size_t bufStart, playerbytes;
int cmd, param1;
const char *s;
// parse the message
while( 1 )
{
if( MSG_CheckOverflow( msg ))
{
Host_Error( "CL_ParseServerMessage: overflow!\n" );
return;
}
// mark start position
bufStart = MSG_GetNumBytesRead( msg );
// end of message (align bits)
if( MSG_GetNumBitsLeft( msg ) < 8 )
break;
cmd = MSG_ReadServerCmd( msg );
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
if( CL_ParseCommonDLLMessage( msg, PROTO_GOLDSRC, cmd, bufStart ))
continue;
// other commands
switch( cmd )
{
case svc_bad:
Host_Error( "svc_bad\n" );
break;
case svc_nop:
case svc_spawnstatic:
case svc_goldsrc_damage:
case svc_goldsrc_killedmonster:
case svc_goldsrc_foundsecret:
// this does nothing
break;
case svc_disconnect:
s = MSG_ReadString( msg );
if( COM_CheckStringEmpty( s ))
Con_Printf( "Server issued disconnect. Reason: %s\n", s );
CL_Drop ();
Host_AbortCurrentFrame ();
break;
case svc_event:
MSG_StartBitWriting( msg );
CL_ParseEvent( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_goldsrc_version:
param1 = MSG_ReadLong( msg );
if( param1 != PROTOCOL_GOLDSRC_VERSION )
Host_Error( "Server use invalid protocol (%i should be %i)\n", param1, PROTOCOL_GOLDSRC_VERSION );
break;
case svc_setview:
CL_ParseViewEntity( msg );
break;
case svc_sound:
CL_ParseSoundPacketGS( msg );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_time:
CL_ParseServerTime( msg, PROTO_GOLDSRC );
break;
case svc_print:
Con_Printf( "%s", MSG_ReadString( msg ));
break;
case svc_stufftext:
s = MSG_ReadString( msg );
if( cl_trace_stufftext.value )
{
size_t len = Q_strlen( s );
Con_Printf( "Stufftext: %s%c", s, len && s[len-1] == '\n' ? '\0' : '\n' );
}
#ifdef HACKS_RELATED_HLMODS
// disable Cry Of Fear antisave protection
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
break; // too early
#endif
Cbuf_AddFilteredText( s );
break;
case svc_setangle:
CL_ParseSetAngle( msg );
break;
case svc_goldsrc_serverinfo:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, PROTO_GOLDSRC );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg, PROTO_GOLDSRC );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, PROTO_GOLDSRC );
break;
case svc_goldsrc_deltadescription:
Delta_ParseTableField_GS( msg );
break;
case svc_clientdata:
MSG_StartBitWriting( msg );
CL_ParseClientData( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_goldsrc_stopsound:
param1 = MSG_ReadWord( msg );
S_StopSound( param1 >> 3, param1 & 7, NULL );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_pings:
MSG_StartBitWriting( msg );
CL_UpdateUserPings( msg );
MSG_EndBitWriting( msg );
break;
case svc_particle:
CL_ParseParticles( msg, PROTO_GOLDSRC );
break;
case svc_event_reliable:
MSG_StartBitWriting( msg );
CL_ParseReliableEvent( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
MSG_StartBitWriting( msg );
CL_ParseBaseline( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
break;
case svc_setpause:
cl.paused = ( MSG_ReadByte( msg ) != 0 );
break;
case svc_signonnum:
CL_ParseSignon( msg, PROTO_GOLDSRC );
break;
case svc_centerprint:
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
break;
case svc_goldsrc_spawnstaticsound:
CL_ParseSpawnStaticSound( msg );
break;
case svc_finale:
CL_ParseFinaleCutscene( msg, 2 );
break;
case svc_restore:
CL_ParseRestore( msg );
break;
case svc_cutscene:
CL_ParseFinaleCutscene( msg, 3 );
break;
case svc_goldsrc_decalname:
param1 = MSG_ReadByte( msg );
s = MSG_ReadString( msg );
Q_strncpy( host.draw_decals[param1], s, sizeof( host.draw_decals[param1] ));
break;
case svc_addangle:
CL_ParseAddAngle( msg );
break;
case svc_goldsrc_newusermsg:
CL_RegisterUserMessage( msg, PROTO_GOLDSRC );
break;
case svc_packetentities:
playerbytes = CL_ParsePacketEntitiesGS( msg, false );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_deltapacketentities:
playerbytes = CL_ParsePacketEntitiesGS( msg, true );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_choke:
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
break;
case svc_resourcelist:
MSG_StartBitWriting( msg );
CL_ParseResourceList( msg, PROTO_GOLDSRC );
MSG_EndBitWriting( msg );
break;
case svc_goldsrc_newmovevars:
CL_ParseNewMovevars( msg );
break;
case svc_resourcerequest:
CL_ParseResourceRequest( msg );
break;
case svc_customization:
CL_ParseCustomization( msg );
break;
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
case svc_soundfade:
CL_ParseSoundFade( msg );
break;
case svc_filetxferfailed:
CL_ParseFileTransferFailed( msg );
break;
case svc_hltv:
CL_ParseHLTV( msg );
break;
case svc_voiceinit:
CL_ParseVoiceInit( msg );
break;
case svc_voicedata:
CL_ParseVoiceData( msg, PROTO_GOLDSRC );
cl.frames[cl.parsecountmod].graphdata.voicebytes += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_goldsrc_sendextrainfo:
CL_ParseExtraInfo( msg );
break;
case svc_goldsrc_timescale:
// we can set sys_timescale to anything we want but in GoldSrc it's locked for
// HLTV and demoplayback. Do we really want to have it then if both are out of scope?
Con_Reportf( S_ERROR "%s: svc_goldsrc_timescale: implement me!\n", __func__ );
MSG_ReadFloat( msg );
break;
case svc_goldsrc_sendcvarvalue:
CL_ParseCvarValue( msg, false, PROTO_GOLDSRC );
break;
case svc_goldsrc_sendcvarvalue2:
CL_ParseCvarValue( msg, true, PROTO_GOLDSRC );
break;
case svc_exec:
CL_ParseExec( msg );
break;
default:
CL_ParseUserMessage( msg, cmd, PROTO_LEGACY );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
break;
}
}
}

View File

@@ -59,7 +59,7 @@ void GAME_EXPORT CL_PopPMStates( void )
CL_IsPredicted
===============
*/
static qboolean CL_IsPredicted( void )
qboolean CL_IsPredicted( void )
{
if( cl_nopred.value || cl.intermission )
return false;
@@ -544,8 +544,8 @@ void GAME_EXPORT CL_SetSolidPlayers( int playernum )
// some fields needs to be override from cls.predicted_players
VectorCopy( player->origin, pe->origin );
VectorCopy( player->angles, pe->angles );
VectorCopy( host.player_mins[player->usehull], pe->mins );
VectorCopy( host.player_maxs[player->usehull], pe->maxs );
VectorCopy( clgame.pmove->player_mins[player->usehull], pe->mins );
VectorCopy( clgame.pmove->player_maxs[player->usehull], pe->maxs );
pe->movetype = player->movetype;
pe->solid = player->solid;
}
@@ -853,7 +853,7 @@ static void CL_SetupPMove( playermove_t *pmove, const local_state_t *from, const
VectorCopy( cd->vuser4, pmove->vuser4 );
pmove->cmd = *ucmd; // copy current cmds
Q_strncpy( pmove->physinfo, cls.physinfo, sizeof( pmove->physinfo ));
Q_strncpy( pmove->physinfo, cls.physinfo, MAX_INFO_STRING );
}
static const void CL_FinishPMove( const playermove_t *pmove, local_state_t *to )

View File

@@ -22,24 +22,22 @@ GNU General Public License for more details.
#include "hltv.h"
#include "input.h"
enum {
STAT_HEALTH = 0,
STAT_FRAGS,
STAT_WEAPON,
STAT_AMMO,
STAT_ARMOR,
STAT_WEAPONFRAME,
STAT_SHELLS,
STAT_NAILS,
STAT_ROCKETS,
STAT_CELLS,
STAT_ACTIVEWEAPON,
STAT_TOTALSECRETS,
STAT_TOTALMONSTERS,
STAT_SECRETS, // bumped on client side by svc_foundsecret
STAT_MONSTERS, // bumped by svc_killedmonster
MAX_STATS = 32,
};
#define STAT_HEALTH 0
#define STAT_FRAGS 1
#define STAT_WEAPON 2
#define STAT_AMMO 3
#define STAT_ARMOR 4
#define STAT_WEAPONFRAME 5
#define STAT_SHELLS 6
#define STAT_NAILS 7
#define STAT_ROCKETS 8
#define STAT_CELLS 9
#define STAT_ACTIVEWEAPON 10
#define STAT_TOTALSECRETS 11
#define STAT_TOTALMONSTERS 12
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret
#define STAT_MONSTERS 14 // bumped by svc_killedmonster
#define MAX_STATS 32
static char cmd_buf[8192];
static char msg_buf[8192];
@@ -213,7 +211,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
clgame.maxEntities = GI->max_edicts;
clgame.maxEntities = bound( 600, clgame.maxEntities, MAX_EDICTS );
clgame.maxModels = MAX_MODELS;
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), sizeof( clgame.maptitle ));
Q_strncpy( clgame.maptitle, MSG_ReadString( msg ), MAX_STRING );
// Re-init hud video, especially if we changed game directories
clgame.dllFuncs.pfnVidInit();
@@ -330,7 +328,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
clgame.movevars.gravity = 800.0f; // quake doesn't write gravity in demos
clgame.movevars.maxvelocity = 2000.0f;
clgame.oldmovevars = clgame.movevars;
memcpy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
}
/*
@@ -431,7 +429,7 @@ static void CL_ParseQuakeEntityData( sizebuf_t *msg, int bits )
cls.signon = SIGNONS;
// Clear loading plaque.
CL_SignonReply( PROTO_QUAKE );
CL_SignonReply ();
}
// alloc next slot to store update
@@ -622,7 +620,7 @@ static void CL_ParseQuakeDamage( sizebuf_t *msg )
/*
===================
CL_ParseStaticEntity
CL_ParseQuakeStaticEntity
===================
*/
@@ -648,7 +646,7 @@ static void CL_ParseQuakeStaticEntity( sizebuf_t *msg )
i = clgame.numStatics;
if( i >= MAX_STATIC_ENTITIES )
{
Con_Printf( S_ERROR "%s: static entities limit exceeded!\n", __func__ );
Con_Printf( S_ERROR "CL_ParseStaticEntity: static entities limit exceeded!\n" );
return;
}
@@ -699,7 +697,7 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
newnum = MSG_ReadWord( msg ); // entnum
if( newnum >= clgame.maxEntities )
Host_Error( "%s: no free edicts\n", __func__ );
Host_Error( "CL_AllocEdict: no free edicts\n" );
// parse baseline
memset( &state, 0, sizeof( state ));
@@ -717,7 +715,8 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
ent = CL_EDICT_NUM( newnum );
ent->index = newnum;
ent->player = CL_IsPlayerIndex( newnum );
ent->prevstate = ent->baseline = state;
memcpy( &ent->baseline, &state, sizeof( entity_state_t ));
memcpy( &ent->prevstate, &state, sizeof( entity_state_t ));
}
/*
@@ -779,7 +778,7 @@ static void CL_ParseQuakeSignon( sizebuf_t *msg )
int i = MSG_ReadByte( msg );
if( i == 3 ) cls.signon = SIGNONS - 1;
Con_Reportf( "%s: %d\n", __func__, i );
Con_Reportf( "CL_Signon: %d\n", i );
}
/*
@@ -845,7 +844,7 @@ static void CL_QuakeExecStuff( void )
while( 1 )
{
// skip whitespace up to a /n
while( *text && ((byte)*text ) <= ' ' && *text != '\r' && *text != '\n' )
while( *text && ((byte)*text) <= ' ' && *text != '\r' && *text != '\n' )
text++;
if( *text == '\n' || *text == '\r' )
@@ -887,21 +886,38 @@ CL_ParseQuakeMessage
==================
*/
void CL_ParseQuakeMessage( sizebuf_t *msg )
void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message )
{
int cmd, param1, param2;
size_t bufStart;
const char *str;
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
CL_Parse_Debug( true ); // begin parsing
// init excise buffer
MSG_Init( &msg_demo, "UserMsg", msg_buf, sizeof( msg_buf ));
if( normal_message )
{
// assume no entity/player update this packet
if( cls.state == ca_active )
{
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
}
else
{
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
}
}
// parse the message
while( 1 )
{
if( MSG_CheckOverflow( msg ))
{
Host_Error( "%s: overflow!\n", __func__ );
Host_Error( "CL_ParseServerMessage: overflow!\n" );
return;
}
@@ -950,7 +966,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
break;
case svc_time:
Cbuf_AddText( "\n" ); // new frame was started
CL_ParseServerTime( msg, PROTO_QUAKE );
CL_ParseServerTime( msg );
break;
case svc_print:
str = MSG_ReadString( msg );
@@ -1092,11 +1108,14 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
}
break;
default:
Host_Error( "%s: Illegible server message\n", __func__ );
Host_Error( "CL_ParseServerMessage: Illegible server message\n" );
break;
}
}
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
CL_Parse_Debug( false ); // done
// now process packet.
CL_ProcessPacket( &cl.frames[cl.parsecountmod] );

View File

@@ -20,7 +20,7 @@ GNU General Public License for more details.
int R_FatPVS( const vec3_t org, float radius, byte *visbuffer, qboolean merge, qboolean fullvis )
{
return Mod_FatPVS( org, radius, visbuffer, world.visbytes, merge, fullvis, false );
return Mod_FatPVS( org, radius, visbuffer, world.visbytes, merge, fullvis );
}
lightstyle_t *CL_GetLightStyle( int number )
@@ -170,12 +170,6 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
return refState.width;
case PARM_SCREEN_HEIGHT:
return refState.height;
case PARM_SKY_SPHERE:
return FBitSet( world.flags, FWORLD_SKYSPHERE ) && !FBitSet( world.flags, FWORLD_CUSTOM_SKYBOX );
case PARM_SURF_SAMPLESIZE:
if( arg >= 0 && arg < cl.worldmodel->numsurfaces )
return Mod_SampleSizeForFace( &cl.worldmodel->surfaces[arg] );
return LM_SAMPLE_SIZE;
default:
// indicates call from client.dll
if( checkRef )
@@ -347,7 +341,7 @@ qboolean R_InitRenderAPI( void )
{
if( clgame.dllFuncs.pfnGetRenderInterface( CL_RENDER_INTERFACE_VERSION, &gRenderAPI, &clgame.drawFuncs ))
{
Con_Reportf( "%s: ^2initailized extended RenderAPI ^7ver. %i\n", __func__, CL_RENDER_INTERFACE_VERSION );
Con_Reportf( "CL_LoadProgs: ^2initailized extended RenderAPI ^7ver. %i\n", CL_RENDER_INTERFACE_VERSION );
return true;
}

View File

@@ -24,7 +24,7 @@ CVAR_DEFINE_AUTO( scr_centertime, "2.5", 0, "centerprint hold time" );
CVAR_DEFINE_AUTO( scr_loading, "0", 0, "loading bar progress" );
CVAR_DEFINE_AUTO( scr_download, "-1", 0, "downloading bar progress" );
CVAR_DEFINE( scr_viewsize, "viewsize", "120", FCVAR_ARCHIVE, "screen size (quake only)" );
CVAR_DEFINE_AUTO( cl_testlights, "0", FCVAR_CHEAT, "test dynamic lights" );
CVAR_DEFINE_AUTO( cl_testlights, "0", 0, "test dynamic lights" );
CVAR_DEFINE( cl_allow_levelshots, "allow_levelshots", "0", FCVAR_ARCHIVE, "allow engine to use indivdual levelshots instead of 'loading' image" );
CVAR_DEFINE_AUTO( cl_levelshot_name, "*black", 0, "contains path to current levelshot" );
static CVAR_DEFINE_AUTO( cl_envshot_size, "256", FCVAR_ARCHIVE, "envshot size of cube side" );
@@ -32,7 +32,6 @@ CVAR_DEFINE_AUTO( v_dark, "0", 0, "starts level from dark screen" );
static CVAR_DEFINE_AUTO( net_speeds, "0", FCVAR_ARCHIVE, "show network packets" );
static CVAR_DEFINE_AUTO( cl_showfps, "0", FCVAR_ARCHIVE, "show client fps" );
static CVAR_DEFINE_AUTO( cl_showpos, "0", FCVAR_ARCHIVE, "show local player position and velocity" );
static CVAR_DEFINE_AUTO( cl_showents, "0", FCVAR_ARCHIVE | FCVAR_CHEAT, "show entities information (largely undone)" );
typedef struct
{
@@ -123,7 +122,7 @@ void SCR_DrawPos( void )
if( cls.state != ca_active || !cl_showpos.value || cl.background )
return;
ent = CL_EDICT_NUM( cl.playernum + 1 );
ent = CL_GetLocalPlayer();
speed = VectorLength( cl.simvel );
Q_snprintf( msg, MAX_SYSPATH,
@@ -141,68 +140,6 @@ void SCR_DrawPos( void )
Con_DrawString( refState.width / 2, 4, msg, color );
}
/*
==============
SCR_DrawEnts
==============
*/
void SCR_DrawEnts( void )
{
rgba_t color = { 255, 255, 255, 255 };
int i;
if( cls.state != ca_active || !cl_showents.value || ( cl.maxclients > 1 && !cls.demoplayback ))
return;
// this probably better hook CL_AddVisibleEntities
// as entities might get added by client.dll
for( i = 0; i < clgame.maxEntities; i++ )
{
const cl_entity_t *ent = &clgame.entities[i];
string msg;
vec3_t screen, pos;
if( ent->curstate.messagenum != cl.parsecount )
continue;
VectorCopy( ent->origin, pos );
if( ent->model != NULL )
{
vec3_t v;
// simple model type filter
if( cl_showents.value > 1 )
{
if( ent->model->type != (modtype_t)( cl_showents.value - 2 ))
continue;
}
VectorAverage( ent->model->mins, ent->model->maxs, v );
VectorAdd( pos, v, pos );
}
if( !ref.dllFuncs.WorldToScreen( pos, screen ))
{
Q_snprintf( msg, sizeof( msg ),
"entity %d\n"
"model %s\n"
"movetype %d\n",
ent->index,
ent->model ? ent->model->name : "(null)",
ent->curstate.movetype );
screen[0] = 0.5f * screen[0] * refState.width;
screen[1] = -0.5f * screen[1] * refState.height;
screen[0] += 0.5f * refState.width;
screen[1] += 0.5f * refState.height;
Con_DrawString( screen[0], screen[1], msg, color );
}
}
}
/*
==============
SCR_NetSpeeds
@@ -408,7 +345,7 @@ void SCR_MakeScreenShot( void )
SCR_DrawPlaque
================
*/
static qboolean SCR_DrawPlaque( void )
static void SCR_DrawPlaque( void )
{
if(( cl_allow_levelshots.value && !cls.changelevel ) || cl.background )
{
@@ -416,11 +353,7 @@ static qboolean SCR_DrawPlaque( void )
ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1, levelshot );
if( !cl.background ) CL_DrawHUD( CL_LOADING );
return true;
}
return false;
}
/*
@@ -430,10 +363,15 @@ SCR_BeginLoadingPlaque
*/
void SCR_BeginLoadingPlaque( qboolean is_background )
{
float oldclear = 0;;
S_StopAllSounds( true );
cl.audio_prepped = false; // don't play ambients
cl.video_prepped = false;
if( cls.key_dest == key_menu && !cls.changedemo && !is_background )
if( !Host_IsDedicated() )
oldclear = gl_clear.value;
if( CL_IsInMenu( ) && !cls.changedemo && !is_background )
{
UI_SetActiveMenu( false );
if( cls.state == ca_disconnected && !(GameState->curstate == STATE_RUNFRAME && GameState->nextstate != STATE_RUNFRAME) )
@@ -446,15 +384,18 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
if( cls.key_dest == key_console )
return;
if( !Host_IsDedicated() )
gl_clear.value = 0.0f;
if( is_background ) IN_MouseSavePos( );
cls.draw_changelevel = !is_background;
SCR_UpdateScreen();
// set video_prepped after update screen, so engine can draw last remaining frame
cl.video_prepped = false;
cls.disable_screen = host.realtime;
cl.background = is_background; // set right state before svc_serverdata is came
if( !Host_IsDedicated() )
gl_clear.value = oldclear;
// SNDDMA_LockSound();
}
@@ -504,7 +445,7 @@ void SCR_TileClear( void )
int i, top, bottom, left, right;
dirty_t clear;
if( likely( scr_viewsize.value >= 120 ))
if( scr_viewsize.value >= 120 )
return; // full screen rendering
// erase rect will be the union of the past three frames
@@ -582,8 +523,6 @@ text to the screen.
*/
void SCR_UpdateScreen( void )
{
qboolean screen_redraw = true; // assume screen has been redrawn
if( !V_PreRender( )) return;
switch( cls.state )
@@ -594,7 +533,7 @@ void SCR_UpdateScreen( void )
case ca_connecting:
case ca_connected:
case ca_validate:
screen_redraw = SCR_DrawPlaque();
SCR_DrawPlaque();
break;
case ca_active:
Con_RunConsole ();
@@ -604,15 +543,11 @@ void SCR_UpdateScreen( void )
SCR_DrawCinematic();
break;
default:
Host_Error( "%s: bad cls.state\n", __func__ );
Host_Error( "SCR_UpdateScreen: bad cls.state\n" );
break;
}
// during changelevel we might have a few frames when we have nothing to draw
// (assuming levelshots are off) and drawing 2d on top of nothing or cleared screen
// is ugly, specifically with Adreno and ImgTec GPUs
if( screen_redraw || !cls.changelevel || !cls.changedemo )
V_PostRender();
V_PostRender();
}
/*
@@ -818,9 +753,6 @@ void SCR_Init( void )
Cvar_RegisterVariable( &net_speeds );
Cvar_RegisterVariable( &cl_showfps );
Cvar_RegisterVariable( &cl_showpos );
#ifdef _DEBUG
Cvar_RegisterVariable( &cl_showents );
#endif // NDEBUG
// register our commands
Cmd_AddCommand( "skyname", CL_SetSky_f, "set new skybox by basename" );

File diff suppressed because it is too large Load Diff

View File

@@ -77,6 +77,7 @@ void R_MultiGunshot( const vec3_t org, const vec3_t dir, const vec3_t noise, int
void R_FireField( float *org, int radius, int modelIndex, int count, int flags, float life );
void R_PlayerSprites( int client, int modelIndex, int count, int size );
void R_Sprite_WallPuff( struct tempent_s *pTemp, float scale );
void R_DebugParticle( const vec3_t pos, byte r, byte g, byte b );
void R_RicochetSound( const vec3_t pos );
struct dlight_s *CL_AllocDlight( int key );
struct dlight_s *CL_AllocElight( int key );

View File

@@ -35,7 +35,7 @@ static void V_CalcViewRect( void )
int sb_lines;
float size;
if( Host_IsQuakeCompatible( ))
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
{
// intermission is always full screen
if( cl.intermission ) size = 120.0f;
@@ -144,9 +144,7 @@ static void V_SetRefParams( ref_params_t *fd )
VectorCopy( cl.viewangles, fd->cl_viewangles );
fd->health = cl.local.health;
VectorCopy( cl.crosshairangle, fd->crosshairangle );
if( Host_IsQuakeCompatible( ))
fd->viewsize = scr_viewsize.value;
else fd->viewsize = 120.0f;
fd->viewsize = scr_viewsize.value;
VectorCopy( cl.punchangle, fd->punchangle );
fd->maxclients = cl.maxclients;
@@ -343,7 +341,7 @@ qboolean V_PreRender( void )
{
if(( host.realtime - cls.disable_screen ) > cl_timeout.value )
{
Con_Reportf( "%s: loading plaque timed out\n", __func__ );
Con_Reportf( "V_PreRender: loading plaque timed out\n" );
cls.disable_screen = 0.0f;
}
return false;
@@ -508,6 +506,7 @@ V_PostRender
*/
void V_PostRender( void )
{
static double oldtime;
qboolean draw_2d = false;
ref.dllFuncs.R_AllowFog( false );
@@ -534,7 +533,6 @@ void V_PostRender( void )
SCR_RSpeeds();
SCR_NetSpeeds();
SCR_DrawPos();
SCR_DrawEnts();
SCR_DrawNetGraph();
SV_DrawOrthoTriangles();
CL_DrawDemoRecording();

View File

@@ -129,6 +129,7 @@ typedef struct
// misc local info
qboolean repredicting; // repredicting in progress
qboolean thirdperson;
qboolean apply_effects; // local player will not added but we should apply their effects: flashlight etc
float idealpitch;
int viewmodel;
@@ -228,7 +229,7 @@ typedef struct
char serverinfo[MAX_SERVERINFO_STRING];
player_info_t players[MAX_CLIENTS]; // collected info about all other players include himself
double lastresourcecheck;
qboolean http_download;
string downloadUrl;
event_state_t events;
// predicting stuff but not only...
@@ -275,10 +276,6 @@ typedef struct
model_t *worldmodel; // pointer to world
int lostpackets; // count lost packets and show dialog in menu
double frametime_remainder;
uint worldmapCRC;
} client_t;
/*
@@ -494,6 +491,7 @@ typedef struct
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
efrag_t *free_efrags; // linked efrags
cl_entity_t viewent; // viewmodel
qboolean client_dll_uses_sdl;
@@ -510,9 +508,8 @@ typedef struct
player_info_t playerinfo; // local playerinfo
gameui_draw_t ds; // draw2d stuff (menu images)
gameinfo2_t gameInfo; // current gameInfo
gameinfo2_t *modsInfo; // simplified gameInfo for MainUI, allocated by demand
GAMEINFO **oldModsInfo; // simplified gameInfo for older MainUI, allocated by demand
GAMEINFO gameInfo; // current gameInfo
GAMEINFO *modsInfo[MAX_MODS]; // simplified gameInfo for MainUI
ui_globalvars_t *globals;
@@ -521,7 +518,7 @@ typedef struct
int logo_yres;
float logo_length;
qboolean use_extended_api;
qboolean use_text_api;
} gameui_static_t;
typedef struct
@@ -542,8 +539,12 @@ typedef struct
poolhandle_t mempool; // client premamnent pool: edicts etc
int signon; // 0 to SIGNONS, for the signon sequence.
netadr_t hltv_listen_address;
int signon; // 0 to SIGNONS, for the signon sequence.
int quakePort; // a 16 bit value that allows quake servers
// to work around address translating routers
// g-cont. this port allow many copies of engine in multiplayer game
// connection information
char servername[MAX_QPATH]; // name of server from original connect
double connect_time; // for connection retransmits
@@ -627,14 +628,12 @@ typedef struct
char internetservers_query[512]; // cached query
uint32_t internetservers_query_len;
// multiprotocol support
connprotocol_t legacymode;
// legacy mode support
qboolean legacymode; // one-way 48 protocol compatibility
netadr_t legacyserver;
int extensions;
netadr_t serveradr;
// do we accept utf8 as input
qboolean accept_utf8;
} client_static_t;
#ifdef __cplusplus
@@ -653,13 +652,15 @@ extern gameui_static_t gameui;
//
// cvars
//
extern convar_t showpause;
extern convar_t mp_decals;
extern convar_t cl_logomaxdim;
extern convar_t cl_logofile;
extern convar_t cl_logocolor;
extern convar_t cl_allow_download;
extern convar_t cl_allow_upload;
extern convar_t cl_download_ingame;
extern convar_t cl_nopred;
extern convar_t cl_timeout;
extern convar_t cl_nodelta;
extern convar_t cl_interp;
extern convar_t cl_nointerp;
extern convar_t cl_showerror;
@@ -672,11 +673,13 @@ extern convar_t cl_updaterate;
extern convar_t cl_solid_players;
extern convar_t cl_idealpitchscale;
extern convar_t cl_allow_levelshots;
extern convar_t cl_lightstyle_lerping;
extern convar_t cl_draw_particles;
extern convar_t cl_draw_tracers;
extern convar_t cl_levelshot_name;
extern convar_t cl_draw_beams;
extern convar_t cl_clockreset;
extern convar_t cl_fixtimerate;
extern convar_t hud_fontscale;
extern convar_t hud_fontrender;
extern convar_t hud_scale;
@@ -754,7 +757,7 @@ qboolean CL_PrecacheResources( void );
void CL_SetupOverviewParams( void );
void CL_UpdateFrameLerp( void );
int CL_IsDevOverviewMode( void );
void CL_SignonReply( connprotocol_t proto );
void CL_SignonReply( void );
void CL_ClearState( void );
//
@@ -778,14 +781,13 @@ void CL_Demos_f( void );
void CL_DeleteDemo_f( void );
void CL_Record_f( void );
void CL_Stop_f( void );
void CL_ListDemo_f( void );
int CL_GetDemoComment( const char *demoname, char *comment );
//
// cl_events.c
//
void CL_ParseEvent( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseReliableEvent( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseEvent( sizebuf_t *msg );
void CL_ParseReliableEvent( sizebuf_t *msg );
void CL_SetEventIndex( const char *szEvName, int ev_index );
void CL_PlaybackEvent( int flags, const edict_t *pInvoker, word eventindex, float delay, float *origin,
float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
@@ -847,14 +849,14 @@ _inline cl_entity_t *CL_EDICT_NUM( int n )
{
if( !clgame.entities )
{
Host_Error( "%s: clgame.entities is NULL\n", __func__ );
Host_Error( "CL_EDICT_NUM: clgame.entities is NULL\n");
return NULL;
}
if(( n >= 0 ) && ( n < clgame.maxEntities ))
return clgame.entities + n;
Host_Error( "%s: bad number %i\n", __func__, n );
Host_Error( "CL_EDICT_NUM: bad number %i\n", n );
return NULL;
}
@@ -862,21 +864,20 @@ _inline cl_entity_t *CL_EDICT_NUM( int n )
// cl_parse.c
//
void CL_ParseSetAngle( sizebuf_t *msg );
void CL_ParseServerData( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseLightStyle( sizebuf_t *msg, connprotocol_t proto );
void CL_UpdateUserinfo( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseServerData( sizebuf_t *msg, qboolean legacy );
void CL_ParseLightStyle( sizebuf_t *msg );
void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy );
void CL_ParseResource( sizebuf_t *msg );
void CL_ParseClientData( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseClientData( sizebuf_t *msg );
void CL_UpdateUserPings( sizebuf_t *msg );
void CL_ParseParticles( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseParticles( sizebuf_t *msg );
void CL_ParseRestoreSoundPacket( sizebuf_t *msg );
void CL_ParseBaseline( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseSignon( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy );
void CL_ParseSignon( sizebuf_t *msg );
void CL_ParseRestore( sizebuf_t *msg );
void CL_ParseStaticDecal( sizebuf_t *msg );
void CL_ParseAddAngle( sizebuf_t *msg );
void CL_RegisterUserMessage( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResourceList( sizebuf_t *msg, connprotocol_t proto );
void CL_RegisterUserMessage( sizebuf_t *msg );
void CL_ParseMovevars( sizebuf_t *msg );
void CL_ParseResourceRequest( sizebuf_t *msg );
void CL_ParseCustomization( sizebuf_t *msg );
@@ -885,36 +886,27 @@ void CL_ParseSoundFade( sizebuf_t *msg );
void CL_ParseFileTransferFailed( sizebuf_t *msg );
void CL_ParseHLTV( sizebuf_t *msg );
void CL_ParseDirector( sizebuf_t *msg );
void CL_ParseVoiceInit( sizebuf_t *msg );
void CL_ParseVoiceData( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseResLocation( sizebuf_t *msg );
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto );
void CL_ParseServerMessage( sizebuf_t *msg );
qboolean CL_ParseCommonDLLMessage( sizebuf_t *msg, connprotocol_t proto, int svc_num, int startoffset );
void CL_ParseTempEntity( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext );
void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message );
void CL_ParseTempEntity( sizebuf_t *msg );
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
qboolean CL_RequestMissingResources( void );
void CL_RegisterResources( sizebuf_t *msg, connprotocol_t proto );
void CL_RegisterResources ( sizebuf_t *msg );
void CL_ParseViewEntity( sizebuf_t *msg );
void CL_ParseServerTime( sizebuf_t *msg, connprotocol_t proto );
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num, connprotocol_t proto );
void CL_ParseServerTime( sizebuf_t *msg );
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num );
void CL_ParseFinaleCutscene( sizebuf_t *msg, int level );
void CL_ParseTextMessage( sizebuf_t *msg );
void CL_ParseExec( sizebuf_t *msg );
void CL_BatchResourceRequest( qboolean initialize );
int CL_EstimateNeededResources( void );
//
// cl_parse_48.c
//
void CL_ParseLegacyServerMessage( sizebuf_t *msg );
void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message );
void CL_LegacyPrecache_f( void );
//
// cl_parse_gs.c
//
void CL_ParseGoldSrcServerMessage( sizebuf_t *msg );
//
// cl_scrn.c
//
@@ -930,7 +922,6 @@ void SCR_NetSpeeds( void );
void SCR_RSpeeds( void );
void SCR_DrawFPS( int height );
void SCR_DrawPos( void );
void SCR_DrawEnts( void );
//
// cl_netgraph.c
@@ -956,6 +947,7 @@ void CL_SetSolidPlayers( int playernum );
void CL_InitClientMove( void );
void CL_PredictMovement( qboolean repredicting );
void CL_CheckPredictionError( void );
qboolean CL_IsPredicted( void );
int CL_WaterEntity( const float *rgflPos );
cl_entity_t *CL_GetWaterEntity( const float *rgflPos );
pmtrace_t *CL_VisTraceLine( vec3_t start, vec3_t end, int flags );
@@ -971,16 +963,14 @@ void CL_SetIdealPitch( void );
//
// cl_qparse.c
//
void CL_ParseQuakeMessage( sizebuf_t *msg );
void CL_ParseQuakeMessage( sizebuf_t *msg, qboolean normal_message );
//
// cl_frame.c
//
struct channel_s;
struct rawchan_s;
qboolean CL_ValidateDeltaPacket( uint oldpacket, frame_t *oldframe );
int CL_UpdateOldEntNum( int oldindex, frame_t *oldframe, entity_state_t **oldent );
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta, connprotocol_t proto );
int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta );
qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType );
void CL_ResetLatchedVars( cl_entity_t *ent, qboolean full_reset );
qboolean CL_GetEntitySpatialization( struct channel_s *ch );
@@ -1030,6 +1020,7 @@ void CL_InitParticles( void );
void CL_ClearParticles( void );
void CL_FreeParticles( void );
void CL_InitTempEnts( void );
void CL_ClearTempEnts( void );
void CL_FreeTempEnts( void );
void CL_TempEntUpdate( void );
void CL_InitViewBeams( void );
@@ -1065,6 +1056,7 @@ int Con_UtfMoveRight( char *str, int pos, int length );
void Con_DefaultColor( int r, int g, int b, qboolean gameui );
cl_font_t *Con_GetCurFont( void );
cl_font_t *Con_GetFont( int num );
void Con_DrawCharacterLen( int number, int *width, int *height );
int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); // legacy, use cl_font.c
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c
void Con_CharEvent( int key );
@@ -1115,7 +1107,7 @@ qboolean UI_MouseInRect( void );
qboolean UI_IsVisible( void );
void UI_ResetPing( void );
void UI_ShowUpdateDialog( qboolean preferStore );
qboolean UI_ShowMessageBox( const char *text );
void UI_ShowMessageBox( const char *text );
void UI_AddTouchButtonToList( const char *name, const char *texture, const char *command, unsigned char *color, int flags );
void UI_ConnectionProgress_Disconnect( void );
void UI_ConnectionProgress_Download( const char *pszFileName, const char *pszServerName, const char *pszServerPath, int iCurrent, int iTotal, const char *comment );
@@ -1169,7 +1161,5 @@ int Key_ToUpper( int key );
void OSK_Draw( void );
extern rgba_t g_color_table[8];
extern triangleapi_t gTriApi;
extern net_api_t gNetApi;
#endif//CLIENT_H

View File

@@ -21,7 +21,6 @@ GNU General Public License for more details.
#include "qfont.h"
#include "wadfile.h"
#include "input.h"
#include "utflib.h"
static CVAR_DEFINE_AUTO( scr_conspeed, "600", FCVAR_ARCHIVE, "console moving speed" );
static CVAR_DEFINE_AUTO( con_notifytime, "3", FCVAR_ARCHIVE, "notify time to live" );
@@ -35,6 +34,7 @@ static CVAR_DEFINE_AUTO( scr_drawversion, "1", FCVAR_ARCHIVE, "draw version in m
static CVAR_DEFINE_AUTO( con_oldfont, "0", 0, "use legacy font from gfx.wad, might be missing or broken" );
static int g_codepage = 0;
static qboolean g_utf8 = false;
static qboolean g_messagemode_privileged = true;
@@ -610,6 +610,19 @@ static void Con_LoadConchars( void )
con.curFont = &con.chars[fontSize];
}
// CP1251 table
int table_cp1251[64] = {
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x007F, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457
};
/*
============================
Con_UtfProcessChar
@@ -619,28 +632,84 @@ Convert utf char to current font's single-byte encoding
*/
int Con_UtfProcessCharForce( int in )
{
// TODO: get rid of global state where possible
static utfstate_t state = { 0 };
static int m = -1, k = 0; //multibyte state
static int uc = 0; //unicode char
int ch = Q_DecodeUTF8( &state, in );
if( !in )
{
m = -1;
k = 0;
uc = 0;
return 0;
}
if( g_codepage == 1251 )
return Q_UnicodeToCP1251( ch );
if( g_codepage == 1252 )
return Q_UnicodeToCP1252( ch );
// Get character length
if(m == -1)
{
uc = 0;
if( in >= 0xF8 )
return 0;
else if( in >= 0xF0 )
uc = in & 0x07, m = 3;
else if( in >= 0xE0 )
uc = in & 0x0F, m = 2;
else if( in >= 0xC0 )
uc = in & 0x1F, m = 1;
else if( in <= 0x7F)
return in; //ascii
// return 0 if we need more chars to decode one
k=0;
return 0;
}
// get more chars
else if( k <= m )
{
uc <<= 6;
uc += in & 0x3F;
k++;
}
if( in > 0xBF || m < 0 )
{
m = -1;
return 0;
}
if( k == m )
{
k = m = -1;
if( g_codepage == 1251 )
{
// cp1251 now
if( uc >= 0x0410 && uc <= 0x042F )
return uc - 0x410 + 0xC0;
if( uc >= 0x0430 && uc <= 0x044F )
return uc - 0x430 + 0xE0;
else
{
int i;
for( i = 0; i < 64; i++ )
if( table_cp1251[i] == uc )
return i + 0x80;
}
}
else if( g_codepage == 1252 )
{
if( uc < 255 )
return uc;
}
return '?'; // not implemented yet
// not implemented yet
return '?';
}
return 0;
}
int GAME_EXPORT Con_UtfProcessChar( int in )
{
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
if( !g_utf8 )
return in;
// otherwise, decode it and convert to selected codepage
return Con_UtfProcessCharForce( in );
else
return Con_UtfProcessCharForce( in );
}
/*
=================
Con_UtfMoveLeft
@@ -650,22 +719,16 @@ get position of previous printful char
*/
int Con_UtfMoveLeft( char *str, int pos )
{
utfstate_t state = { 0 };
int k = 0;
int i;
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
int i, k = 0;
// int j;
if( !g_utf8 )
return pos - 1;
if( pos == 1 )
return 0;
for( i = 0; i < pos - 1; i++ )
{
if( Q_DecodeUTF8( &state, (byte)str[i] ))
k = i + 1;
}
Con_UtfProcessChar( 0 );
if(pos == 1) return 0;
for( i = 0; i < pos-1; i++ )
if( Con_UtfProcessChar( (unsigned char)str[i] ) )
k = i+1;
Con_UtfProcessChar( 0 );
return k;
}
@@ -678,19 +741,17 @@ get next of previous printful char
*/
int Con_UtfMoveRight( char *str, int pos, int length )
{
utfstate_t state = { 0 };
int i;
if( !cls.accept_utf8 ) // incoming character is not a UTF-8 sequence
if( !g_utf8 )
return pos + 1;
Con_UtfProcessChar( 0 );
for( i = pos; i <= length; i++ )
{
if( Q_DecodeUTF8( &state, (byte)str[i] ))
return i + 1;
if( Con_UtfProcessChar( (unsigned char)str[i] ) )
return i+1;
}
return pos + 1;
Con_UtfProcessChar( 0 );
return pos+1;
}
static void Con_DrawCharToConback( int num, const byte *conchars, byte *dest )
@@ -847,6 +908,7 @@ void Con_Print( const char *txt )
static char buf[MAX_PRINT_MSG];
qboolean norefresh = false;
static int lastlength = 0;
static qboolean inupdate;
static int bufpos = 0;
int c, mask = 0;
@@ -937,27 +999,6 @@ void Con_Print( const char *txt )
}
}
/*
================
Con_NXPrintfv
Draw a single debug line with specified height, color and time to live
================
*/
static void Con_NXPrintfv( keydest_t key_dest, const con_nprint_t *info, const char *fmt, va_list va )
{
if( info->index < 0 || info->index >= ARRAYSIZE( con.notify ))
return;
Q_vsnprintf( con.notify[info->index].szNotify, sizeof( con.notify[info->index].szNotify ), fmt, va );
// setup values
con.notify[info->index].key_dest = key_dest;
con.notify[info->index].expire = host.realtime + info->time_to_live;
MakeRGBA( con.notify[info->index].color, (byte)(info->color[0] * 255), (byte)(info->color[1] * 255), (byte)(info->color[2] * 255), 255 );
con.draw_notify = true;
}
/*
================
Con_NPrint
@@ -968,16 +1009,21 @@ Draw a single debug line with specified height
void GAME_EXPORT Con_NPrintf( int idx, const char *fmt, ... )
{
va_list args;
con_nprint_t info =
{
.index = idx,
.time_to_live = 4.0f,
.color = { 1.0f, 1.0f, 1.0f },
};
if( idx < 0 || idx >= MAX_DBG_NOTIFY )
return;
memset( con.notify[idx].szNotify, 0, MAX_STRING );
va_start( args, fmt );
Con_NXPrintfv( key_game, &info, fmt, args );
Q_vsnprintf( con.notify[idx].szNotify, MAX_STRING, fmt, args );
va_end( args );
// reset values
con.notify[idx].key_dest = key_game;
con.notify[idx].expire = host.realtime + 4.0f;
MakeRGBA( con.notify[idx].color, 255, 255, 255, 255 );
con.draw_notify = true;
}
/*
@@ -993,9 +1039,20 @@ void GAME_EXPORT Con_NXPrintf( con_nprint_t *info, const char *fmt, ... )
if( !info ) return;
if( info->index < 0 || info->index >= MAX_DBG_NOTIFY )
return;
memset( con.notify[info->index].szNotify, 0, MAX_STRING );
va_start( args, fmt );
Con_NXPrintfv( key_game, info, fmt, args );
Q_vsnprintf( con.notify[info->index].szNotify, MAX_STRING, fmt, args );
va_end( args );
// setup values
con.notify[info->index].key_dest = key_game;
con.notify[info->index].expire = host.realtime + info->time_to_live;
MakeRGBA( con.notify[info->index].color, (byte)(info->color[0] * 255), (byte)(info->color[1] * 255), (byte)(info->color[2] * 255), 255 );
con.draw_notify = true;
}
/*
@@ -1008,16 +1065,21 @@ Draw a single debug line with specified height (menu version)
void GAME_EXPORT UI_NPrintf( int idx, const char *fmt, ... )
{
va_list args;
con_nprint_t info =
{
.index = idx,
.time_to_live = 4.0f,
.color = { 1.0f, 1.0f, 1.0f },
};
if( idx < 0 || idx >= MAX_DBG_NOTIFY )
return;
memset( con.notify[idx].szNotify, 0, MAX_STRING );
va_start( args, fmt );
Con_NXPrintfv( key_menu, &info, fmt, args );
Q_vsnprintf( con.notify[idx].szNotify, MAX_STRING, fmt, args );
va_end( args );
// reset values
con.notify[idx].key_dest = key_menu;
con.notify[idx].expire = host.realtime + 4.0f;
MakeRGBA( con.notify[idx].color, 255, 255, 255, 255 );
con.draw_notify = true;
}
/*
@@ -1033,9 +1095,20 @@ void GAME_EXPORT UI_NXPrintf( con_nprint_t *info, const char *fmt, ... )
if( !info ) return;
if( info->index < 0 || info->index >= MAX_DBG_NOTIFY )
return;
memset( con.notify[info->index].szNotify, 0, MAX_STRING );
va_start( args, fmt );
Con_NXPrintfv( key_menu, info, fmt, args );
Q_vsnprintf( con.notify[info->index].szNotify, MAX_STRING, fmt, args );
va_end( args );
// setup values
con.notify[info->index].key_dest = key_menu;
con.notify[info->index].expire = host.realtime + info->time_to_live;
MakeRGBA( con.notify[info->index].color, (byte)(info->color[0] * 255), (byte)(info->color[1] * 255), (byte)(info->color[2] * 255), 255 );
con.draw_notify = true;
}
/*
@@ -1052,7 +1125,7 @@ Con_ClearField
*/
static void Con_ClearField( field_t *edit )
{
memset( edit->buffer, 0, sizeof( edit->buffer ));
memset( edit->buffer, 0, MAX_STRING );
edit->cursor = 0;
edit->scroll = 0;
}
@@ -1065,7 +1138,7 @@ Field_Set
static void Field_Set( field_t *f, const char *string )
{
f->scroll = 0;
f->cursor = Q_strncpy( f->buffer, string, sizeof( f->buffer ));
f->cursor = Q_strncpy( f->buffer, string, MAX_STRING );
}
/*
@@ -1371,49 +1444,36 @@ static void Con_HistoryAppend( con_history_t *self, field_t *from )
static void Con_LoadHistory( con_history_t *self )
{
const byte *aFile = FS_LoadFile( "console_history.txt", NULL, true );
const char *pLine, *pFile;
int i, len;
field_t *f;
file_t *fd;
int i;
fd = FS_Open( "console_history.txt", "rb", true );
if( !fd )
if( !aFile )
return;
while( !FS_Eof( fd ))
for( pFile = pLine = (char *)aFile; *pFile; pFile++ )
{
f = &self->lines[self->next % CON_HISTORY];
Con_ClearField( f );
f->widthInChars = con.linewidth;
FS_Gets( fd, f->buffer, sizeof( f->buffer ));
f->cursor = Q_strlen( f->buffer );
// skip empty lines
if( f->cursor == 0 )
if( *pFile != '\n' )
continue;
// skip repeating lines
if( self->next > 0 )
{
field_t *prev;
prev = &self->lines[(self->next - 1) % CON_HISTORY];
if( !Q_stricmp( prev->buffer, f->buffer ))
continue;
}
Con_ClearField( &self->lines[self->next] );
len = Q_min( pFile - pLine + 1, sizeof( f->buffer ));
f = &self->lines[self->next % CON_HISTORY];
f->widthInChars = con.linewidth;
f->cursor = len - 1;
Q_strncpy( f->buffer, pLine, len);
self->next++;
}
FS_Close( fd );
pLine = pFile + 1;
}
for( i = self->next; i < CON_HISTORY; i++ )
{
f = &self->lines[i];
Con_ClearField( f );
f->widthInChars = con.linewidth;
Con_ClearField( &self->lines[i] );
self->lines[i].widthInChars = con.linewidth;
}
self->line = self->next;
@@ -1431,18 +1491,10 @@ static void Con_SaveHistory( con_history_t *self )
if( historyStart < 0 )
historyStart = 0;
f = FS_Open( "console_history.txt", "wb", true );
f = FS_Open( "console_history.txt", "w", true );
for( i = historyStart; i < self->next; i++ )
{
const char *s = self->lines[i % CON_HISTORY].buffer;
// HACKHACK: don't save lines that have something that looks like a password
if( Q_stristr( s, "password" ) || Q_stristr( s, "_pw" ))
continue;
FS_Printf( f, "%s\n", s );
}
FS_Printf( f, "%s\n", self->lines[i % CON_HISTORY].buffer );
FS_Close( f );
}
@@ -1484,9 +1536,6 @@ void Key_Console( int key )
Con_Printf( ">%s\n", con.input.buffer );
// copy line to history buffer
// just in case, remove all CR and LF characters pushing it to the history
// not sure how they get even added in the first place
COM_RemoveLineFeed( con.input.buffer, sizeof( con.input.buffer ));
Con_HistoryAppend( &con.history, &con.input );
Con_ClearField( &con.input );
@@ -1753,7 +1802,7 @@ static void Con_DrawNotify( void )
if( host.allow_console && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" )))
{
for( i = Q_max( 0, CON_LINES_COUNT - con.num_times ); i < CON_LINES_COUNT; i++ )
for( i = CON_LINES_COUNT - con.num_times; i < CON_LINES_COUNT; i++ )
{
con_lineinfo_t *l = &CON_LINES( i );
@@ -2095,7 +2144,7 @@ void Con_RunConsole( void )
g_codepage = 1252;
}
cls.accept_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
g_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
Con_InvalidateFonts();
Con_LoadConchars();
ClearBits( con_charset.flags, FCVAR_CHANGED );
@@ -2133,34 +2182,6 @@ void Con_CharEvent( int key )
}
}
static int Con_LoadSimpleConback( const char *name, int flags )
{
const char *paths[] = {
"gfx/shell/%s.dds",
"gfx/shell/%s.bmp",
"gfx/shell/%s.tga",
"cached/%s640",
"cached/%s",
};
size_t i;
for( i = 0; i < ARRAYSIZE( paths ); i++ )
{
string path;
Q_snprintf( path, sizeof( path ), paths[i], name );
if( g_fsapi.FileExists( path, false ))
{
int gl_texturenum = ref.dllFuncs.GL_LoadTexture( path, NULL, 0, flags );
if( gl_texturenum )
return gl_texturenum;
}
}
return 0;
}
/*
=========
Con_VidInit
@@ -2183,12 +2204,38 @@ void Con_VidInit( void )
Con_LoadConchars();
Con_CheckResize();
#if XASH_LOW_MEMORY
con.background = R_GetBuiltinTexture( REF_GRAY_TEXTURE );
con.background = R_GetBuiltinTexture( REF_BLACK_TEXTURE );
#else
// loading console image
con.background = Con_LoadSimpleConback( host.allow_console ? "conback" : "loading", flags );
if( host.allow_console )
{
// trying to load truecolor image first
if( FS_FileExists( "gfx/shell/conback.bmp", false ) || FS_FileExists( "gfx/shell/conback.tga", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "gfx/shell/conback", NULL, 0, flags );
if( !con.background )
{
if( FS_FileExists( "cached/conback640", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "cached/conback640", NULL, 0, flags );
else if( FS_FileExists( "cached/conback", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "cached/conback", NULL, 0, flags );
}
}
else
{
// trying to load truecolor image first
if( FS_FileExists( "gfx/shell/loading.bmp", false ) || FS_FileExists( "gfx/shell/loading.tga", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "gfx/shell/loading", NULL, 0, flags );
if( !con.background )
{
if( FS_FileExists( "cached/loading640", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "cached/loading640", NULL, 0, flags );
else if( FS_FileExists( "cached/loading", false ))
con.background = ref.dllFuncs.GL_LoadTexture( "cached/loading", NULL, 0, flags );
}
}
if( !con.background ) // last chance - quake conback image
{

View File

@@ -134,7 +134,7 @@ static void Joy_ProcessTrigger( const engineAxis_t engineAxis, short value )
trigThreshold = joy_lt_threshold.value;
break;
default:
Con_Reportf( S_ERROR "%s: invalid axis = %i\n", __func__, engineAxis );
Con_Reportf( S_ERROR "Joy_ProcessTrigger: invalid axis = %i", engineAxis );
break;
}
@@ -205,7 +205,7 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
case JOY_AXIS_PITCH: deadzone = joy_pitch_deadzone.value; break;
case JOY_AXIS_YAW: deadzone = joy_yaw_deadzone.value; break;
default:
Con_Reportf( S_ERROR "%s: invalid axis = %i\n", __func__, engineAxis );
Con_Reportf( S_ERROR "Joy_ProcessStick: invalid axis = %i", engineAxis );
break;
}
@@ -218,7 +218,7 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
// fwd/side axis simulate hat movement
if( ( engineAxis == JOY_AXIS_SIDE || engineAxis == JOY_AXIS_FWD ) &&
( cls.key_dest == key_menu || cls.key_dest == key_console ))
( CL_IsInMenu() || CL_IsInConsole() ) )
{
int val = 0;

View File

@@ -142,7 +142,7 @@ static struct touch_s
touchdefaultbutton_t g_DefaultButtons[256];
int g_LastDefaultButton;
static CVAR_DEFINE_AUTO( touch_in_menu, "0", FCVAR_PRIVILEGED, "draw touch in menu (for internal use only)" );
static CVAR_DEFINE_AUTO( touch_in_menu, "0", FCVAR_FILTERABLE, "draw touch in menu (for internal use only)" );
static CVAR_DEFINE_AUTO( touch_forwardzone, "0.06", FCVAR_FILTERABLE, "forward touch zone" );
static CVAR_DEFINE_AUTO( touch_sidezone, "0.06", FCVAR_FILTERABLE, "side touch zone" );
static CVAR_DEFINE_AUTO( touch_pitch, "90", FCVAR_FILTERABLE, "touch pitch sensitivity" );
@@ -163,8 +163,8 @@ static CVAR_DEFINE_AUTO( touch_dpad_radius, "1.0", FCVAR_FILTERABLE, "dpad radiu
static CVAR_DEFINE_AUTO( touch_joy_radius, "1.0", FCVAR_FILTERABLE, "joy radius multiplier" );
static CVAR_DEFINE_AUTO( touch_move_indicator, "0.0", FCVAR_FILTERABLE, "indicate move events (0 to disable)" );
static CVAR_DEFINE_AUTO( touch_joy_texture, "touch_default/joy", FCVAR_FILTERABLE, "texture for move indicator");
static CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "emulate touch with mouse" );
CVAR_DEFINE_AUTO( touch_enable, DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" );
CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" );
// code looks smaller with it
#define B(x) (button->x)
@@ -333,7 +333,7 @@ void Touch_WriteConfig( void )
if( Sys_CheckParm( "-nowriteconfig" ) || !touch.configchanged || !touch.config_loaded )
return;
Con_DPrintf( "%s: %s\n", __func__, touch_config_file.string );
Con_DPrintf( "Touch_WriteConfig(): %s\n", touch_config_file.string );
Q_snprintf( newconfigfile, sizeof( newconfigfile ), "%s.new", touch_config_file.string );
Q_snprintf( oldconfigfile, sizeof( oldconfigfile ), "%s.bak", touch_config_file.string );
@@ -767,18 +767,14 @@ static void Touch_ReloadConfig_f( void )
touch.state = state_none;
if( touch.edit )
touch.edit->finger = -1;
if( touch.selection )
touch.selection->finger = -1;
touch.edit = touch.selection = NULL;
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
if( touch_in_menu.value )
Cvar_DirectSet( &touch_in_menu, "0" );
if( FS_FileExists( touch_config_file.string, true ))
if( FS_FileExists( touch_config_file.string, true ) )
{
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file.string );
}
else
{
Touch_LoadDefaults_f();
@@ -1014,7 +1010,7 @@ static void Touch_DisableEdit_f( void )
{
Cvar_Set( "touch_in_menu", "0" );
}
else if( cls.key_dest == key_game )
else if( cls.key_dest == key_game )
Touch_WriteConfig();
}
@@ -1068,7 +1064,7 @@ void Touch_Init( void )
return;
touch.mempool = Mem_AllocPool( "Touch" );
//touch.first = touch.last = NULL;
Con_Printf( "%s()\n", __func__ );
Con_Printf( "IN_TouchInit()\n");
touch.move_finger = touch.resize_finger = touch.look_finger = touch.wheel_finger = -1;
touch.state = state_none;
touch.showeditbuttons = true;
@@ -1091,19 +1087,18 @@ void Touch_Init( void )
Touch_AddDefaultButton( "jump", "touch_default/jump", "+jump", 0.880000, 0.227228, 1.000000, 0.454457, color, 2, 1, 0 );
Touch_AddDefaultButton( "attack", "touch_default/shoot", "+attack", 0.760000, 0.530200, 0.880000, 0.757428, color, 2, 1, 0 );
Touch_AddDefaultButton( "attack2", "touch_default/shoot_alt", "+attack2", 0.760000, 0.302971, 0.880000, 0.530200, color, 2, 1, 0 );
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.760000, 0.000000, 0.840000, 0.142222, color, 2, 1, 16 );
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.840000, 0.000000, 0.920000, 0.142222, color, 2, 1, 16 );
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.840000, 0.000000, 0.920000, 0.142222, color, 2, 1, 8 );
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 16 );
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 16 );
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 );
Touch_AddDefaultButton( "reload", "touch_default/reload", "+reload", 0.000000, 0.302971, 0.120000, 0.530200, color, 2, 1, 0 );
Touch_AddDefaultButton( "flashlight", "touch_default/flash_light_filled", "impulse 100", 0.920000, 0.000000, 1.000000, 0.151486, color, 2, 1, 0 );
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.760000, 0.000000, 0.840000, 0.142222, color, 2, 1, 8 );
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 8 );
Touch_AddDefaultButton( "show_numbers", "touch_default/show_weapons", "exec touch_default/numbers.cfg", 0.440000, 0.833171, 0.520000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "duck", "touch_default/crouch", "+duck", 0.880000, 0.757428, 1.000000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "tduck", "touch_default/tduck", ";+duck", 0.560000, 0.833171, 0.620000, 0.946785, color, 2, 1, 0 );
Touch_AddDefaultButton( "edit", "touch_default/settings", "touch_enableedit", 0.420000, 0.000000, 0.500000, 0.151486, color, 2, 1, 32 );
Touch_AddDefaultButton( "menu", "touch_default/menu", "escape", 0.000000, 0.833171, 0.080000, 0.984656, color, 2, 1, 0 );
Touch_AddDefaultButton( "spray", "touch_default/spray", "impulse 201", 0.680000, 0.000000, 0.760000, 0.142222, color, 2, 1, 8 );
Touch_AddDefaultButton( "voicechat", "touch_default/microphone", "+voicerecord", 0.780000, 0.817778, 0.860000, 0.960000, color, 2, 1, 8 );
Touch_AddDefaultButton( "spray", "touch_default/spray", "impulse 201", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 0 );
Cmd_AddCommand( "touch_addbutton", Touch_AddButton_f, "add native touch button" );
Cmd_AddCommand( "touch_removebutton", IN_TouchRemoveButton_f, "remove native touch button" );
@@ -1222,10 +1217,10 @@ static qboolean Touch_IsVisible( touch_button_t *button )
if( FBitSet( button->flags, TOUCH_FL_HIDE ))
return false; // skip hidden
if( FBitSet( button->flags, TOUCH_FL_SP ) && cl.maxclients != 1 )
if( FBitSet( button->flags, TOUCH_FL_SP ) && CL_GetMaxClients() != 1 )
return false; // skip singleplayer(load, save) buttons in multiplayer
if( FBitSet( button->flags, TOUCH_FL_MP ) && cl.maxclients == 1 )
if( FBitSet( button->flags, TOUCH_FL_MP ) && CL_GetMaxClients() == 1 )
return false; // skip multiplayer buttons in singleplayer
return true;
@@ -2127,7 +2122,7 @@ void Touch_KeyEvent( int key, int down )
float x, y;
int finger, xi, yi;
if( !Touch_Emulated( ))
if( !touch_emulate.value )
{
if( touch_enable.value )
return;
@@ -2168,7 +2163,8 @@ void Touch_KeyEvent( int key, int down )
x = xi / SCR_W;
y = yi / SCR_H;
// Con_DPrintf( "event %d %.2f %.2f %.2f %.2f\n", event, x, y, x - lx, y - ly );
Con_DPrintf( "event %d %.2f %.2f %.2f %.2f\n",
event, x, y, x - lx, y - ly );
IN_TouchEvent( event, finger, x, y, x - lx, y - ly );
@@ -2181,11 +2177,6 @@ qboolean Touch_WantVisibleCursor( void )
return ( touch_enable.value && touch_emulate.value ) || touch.clientonly;
}
qboolean Touch_Emulated( void )
{
return touch_emulate.value || touch_in_menu.value;
}
void Touch_Shutdown( void )
{
if( !touch.initialized )

View File

@@ -17,7 +17,6 @@ GNU General Public License for more details.
#include "input.h"
#include "client.h"
#include "vgui_draw.h"
#include "cursor_type.h"
#if XASH_SDL
#include <SDL.h>
@@ -47,8 +46,6 @@ static CVAR_DEFINE_AUTO( cl_forwardspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL
static CVAR_DEFINE_AUTO( cl_backspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default back move speed" );
static CVAR_DEFINE_AUTO( cl_sidespeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default side move speed" );
static CVAR_DEFINE_AUTO( m_grab_debug, "0", FCVAR_PRIVILEGED, "show debug messages on mouse state change" );
/*
================
IN_CollectInputDevices
@@ -118,7 +115,6 @@ static void IN_StartupMouse( void )
Cvar_RegisterVariable( &m_yaw );
Cvar_RegisterVariable( &look_filter );
Cvar_RegisterVariable( &m_rawinput );
Cvar_RegisterVariable( &m_grab_debug );
// You can use -nomouse argument to prevent using mouse from client
// -noenginemouse will disable all mouse input
@@ -127,6 +123,11 @@ static void IN_StartupMouse( void )
in_mouseinitialized = true;
}
void GAME_EXPORT IN_SetCursor( void *hCursor )
{
// stub
}
/*
===========
IN_MouseSavePos
@@ -205,81 +206,68 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
}
}
static void IN_SetRelativeMouseMode( qboolean set, qboolean verbose )
{
static qboolean s_bRawInput;
if( set && !s_bRawInput )
{
#if XASH_SDL == 2
SDL_GetRelativeMouseState( NULL, NULL );
SDL_SetRelativeMouseMode( SDL_TRUE );
#endif
s_bRawInput = true;
if( verbose )
Con_Printf( "%s: true\n", __func__ );
}
else if( !set && s_bRawInput )
{
#if XASH_SDL == 2
SDL_GetRelativeMouseState( NULL, NULL );
SDL_SetRelativeMouseMode( SDL_FALSE );
#endif
s_bRawInput = false;
if( verbose )
Con_Printf( "%s: false\n", __func__ );
}
}
static void IN_SetMouseGrab( qboolean set, qboolean verbose )
{
static qboolean s_bMouseGrab;
if( set && !s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
#endif
s_bMouseGrab = true;
if( verbose )
Con_Printf( "%s: true\n", __func__ );
}
else if( !set && s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif
s_bMouseGrab = false;
if( verbose )
Con_Printf( "%s: false\n", __func__ );
}
}
static void IN_CheckMouseState( qboolean active )
{
qboolean use_raw_input, verbose;
static qboolean s_bRawInput, s_bMouseGrab;
#if XASH_WIN32
use_raw_input = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
qboolean useRawInput = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
#else
use_raw_input = true; // always use SDL code
qboolean useRawInput = true; // always use SDL code
#endif
verbose = m_grab_debug.value ? true : false;
if( m_ignore.value )
active = false;
return;
if( active && use_raw_input && !host.mouse_visible && cls.state == ca_active )
IN_SetRelativeMouseMode( true, verbose );
if( active && useRawInput && !host.mouse_visible && cls.state == ca_active )
{
if( !s_bRawInput )
{
#if XASH_SDL == 2
SDL_GetRelativeMouseState( NULL, NULL );
SDL_SetRelativeMouseMode( SDL_TRUE );
#endif
// Con_Printf( "Enable relative mode\n" );
s_bRawInput = true;
}
}
else
IN_SetRelativeMouseMode( false, verbose );
{
if( s_bRawInput )
{
#if XASH_SDL == 2
SDL_GetRelativeMouseState( NULL, NULL );
SDL_SetRelativeMouseMode( SDL_FALSE );
#endif
// Con_Printf( "Disable relative mode\n" );
s_bRawInput = false;
}
}
if( active && !host.mouse_visible && cls.state == ca_active )
IN_SetMouseGrab( true, verbose );
{
if( !s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_TRUE );
#endif
// Con_Printf( "Enable grab\n" );
s_bMouseGrab = true;
}
}
else
IN_SetMouseGrab( false, verbose );
{
if( s_bMouseGrab )
{
#if XASH_SDL
SDL_SetWindowGrab( host.hWnd, SDL_FALSE );
#endif
// Con_Printf( "Disable grab\n" );
s_bMouseGrab = false;
}
}
}
/*
@@ -332,7 +320,7 @@ static void IN_MouseMove( void )
if( !in_mouseinitialized )
return;
if( Touch_Emulated( ))
if( touch_emulate.value )
{
// touch emulation overrides all input
Touch_KeyEvent( 0, 0 );
@@ -363,7 +351,7 @@ void IN_MouseEvent( int key, int down )
else ClearBits( in_mstate, BIT( key ));
// touch emulation overrides all input
if( Touch_Emulated( ))
if( touch_emulate.value )
{
Touch_KeyEvent( K_MOUSE1 + key, down );
}
@@ -569,9 +557,10 @@ IN_EngineAppendMove
Called from cl_main.c after generating command in client
================
*/
void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active )
void IN_EngineAppendMove( float frametime, void *cmd1, qboolean active )
{
float forward, side, pitch, yaw;
usercmd_t *cmd = cmd1;
if( clgame.dllFuncs.pfnLookEvent )
return;

View File

@@ -25,7 +25,6 @@ INPUT
*/
#include "keydefs.h"
#include "usercmd.h"
//
// input.c
@@ -41,10 +40,11 @@ void IN_DeactivateMouse( void );
void IN_MouseSavePos( void );
void IN_MouseRestorePos( void );
void IN_ToggleClientMouse( int newstate, int oldstate );
void IN_SetCursor( void *hCursor );
uint IN_CollectInputDevices( void );
void IN_LockInputDevices( qboolean lock );
void IN_EngineAppendMove( float frametime, usercmd_t *cmd, qboolean active );
void IN_EngineAppendMove( float frametime, void *cmd, qboolean active );
extern convar_t m_yaw;
extern convar_t m_pitch;
@@ -59,6 +59,7 @@ typedef enum
} touchEventType;
extern convar_t touch_enable;
extern convar_t touch_emulate;
void Touch_Draw( void );
void Touch_SetClientOnly( byte state );
@@ -74,7 +75,6 @@ void Touch_ResetDefaultButtons( void );
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
void Touch_KeyEvent( int key, int down );
qboolean Touch_WantVisibleCursor( void );
qboolean Touch_Emulated( void );
void Touch_NotifyResize( void );
//

View File

@@ -553,7 +553,7 @@ static void Key_AddKeyCommands( int key, const char *kb, qboolean down )
}
buttonPtr = button;
while((((byte)kb[i]) <= ' ' || kb[i] == ';' ) && kb[i] != 0 )
while(( kb[i] <= ' ' || kb[i] == ';' ) && kb[i] != 0 )
i++;
}
@@ -749,10 +749,10 @@ void GAME_EXPORT Key_Event( int key, int down )
if( cls.key_dest == key_menu )
{
// only non printable keys passed
if( !gameui.use_extended_api )
if( !gameui.use_text_api )
Key_EnableTextInput( true, false );
//pass printable chars for old menus
if( !gameui.use_extended_api && !host.textmode && down && ( key >= 32 ) && ( key <= 'z' ) )
if( !gameui.use_text_api && !host.textmode && down && ( key >= 32 ) && ( key <= 'z' ) )
{
if( Key_IsDown( K_SHIFT ) )
{
@@ -840,7 +840,7 @@ void GAME_EXPORT Key_SetKeyDest( int key_dest )
cls.key_dest = key_message;
break;
default:
Host_Error( "%s: wrong destination (%i)\n", __func__, key_dest );
Host_Error( "Key_SetKeyDest: wrong destination (%i)\n", key_dest );
break;
}
}
@@ -1055,16 +1055,18 @@ static qboolean OSK_KeyEvent( int key, int down )
break;
}
ch = (byte)osk.curbutton.val;
// do not pass UTF-8 sequence into the engine, convert it here
if( !cls.accept_utf8 )
ch = Con_UtfProcessCharForce( ch );
if( !Q_stricmp( cl_charset.string, "utf-8" ) )
ch = (unsigned char)osk.curbutton.val;
else
ch = Con_UtfProcessCharForce( (unsigned char)osk.curbutton.val );
if( !ch )
break;
CL_CharEvent( ch );
Con_CharEvent( ch );
if( cls.key_dest == key_menu )
UI_CharEvent ( ch );
break;
}
}
@@ -1119,6 +1121,7 @@ static void OSK_EnableTextInput( qboolean enable, qboolean force )
{
osk.curlayout = 0;
osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x];
}
}

View File

@@ -74,7 +74,7 @@ static void free_winding( winding_t *w )
{
// simple sentinel by Carmack
if( *(unsigned *)w == 0xDEADC0DE )
Host_Error( "%s: freed a freed winding\n", __func__ );
Host_Error( "free_winding: freed a freed winding\n" );
*(unsigned *)w = 0xDEADC0DE;
free( w );
}
@@ -154,7 +154,7 @@ static winding_t *winding_for_plane( const mplane_t *p )
vup[0] = 1;
break;
default:
Host_Error( "%s: no axis found\n", __func__ );
Host_Error( "BaseWindingForPlane: no axis found\n" );
return NULL;
}
@@ -685,9 +685,6 @@ void Mod_CreatePolygonsForHull( int hullnum )
if( hullnum < 1 || hullnum > 3 )
return;
if( !world.num_hull_models )
Mod_InitDebugHulls( mod ); // FIXME: build hulls for separate bmodels (shells, medkits etc)
Con_Printf( "generating polygons for hull %u...\n", hullnum );
start = Sys_DoubleTime();

View File

@@ -8,9 +8,7 @@
struct ref_state_s ref;
ref_globals_t refState;
static const char* r_skyBoxSuffix[SKYBOX_MAX_SIDES] = { "rt", "bk", "lf", "ft", "up", "dn" };
CVAR_DEFINE_AUTO( gl_vsync, "1", FCVAR_ARCHIVE, "enable vertical syncronization" );
CVAR_DEFINE_AUTO( gl_vsync, "0", FCVAR_ARCHIVE, "enable vertical syncronization" );
CVAR_DEFINE_AUTO( r_showtextures, "0", FCVAR_CHEAT, "show all uploaded textures" );
CVAR_DEFINE_AUTO( r_adjust_fov, "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" );
CVAR_DEFINE_AUTO( r_decals, "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
@@ -51,102 +49,13 @@ void R_GetTextureParms( int *w, int *h, int texnum )
if( h ) *h = REF_GET_PARM( PARM_TEX_HEIGHT, texnum );
}
static qboolean CheckSkybox( const char *name, char out[SKYBOX_MAX_SIDES][MAX_STRING] )
{
static const char *skybox_ext[3] = { "dds", "tga", "bmp" };
static const char *skybox_delim[2] = { "", "_" }; // no space for HL style, underscore for Q1 style
int i;
// search for skybox images
for( i = 0; i < ARRAYSIZE( skybox_ext ); i++ )
{
int j;
for( j = 0; j < ARRAYSIZE( skybox_delim ); j++ )
{
int k, num_checked_sides = 0;
for( k = 0; k < SKYBOX_MAX_SIDES; k++ )
{
char sidename[MAX_VA_STRING];
Q_snprintf( sidename, sizeof( sidename ), "%s%s%s.%s", name, skybox_delim[j], r_skyBoxSuffix[k], skybox_ext[i] );
if( g_fsapi.FileExists( sidename, false ))
{
Q_strncpy( out[k], sidename, sizeof( out[k] ));
num_checked_sides++;
}
}
if( num_checked_sides == SKYBOX_MAX_SIDES )
return true; // image exists
}
}
return false;
}
void R_SetupSky( const char *name )
{
string loadname;
char sidenames[SKYBOX_MAX_SIDES][MAX_STRING];
int skyboxTextures[SKYBOX_MAX_SIDES] = { 0 };
int i, len;
qboolean result;
if( !COM_CheckString( name ))
{
ref.dllFuncs.R_SetupSky( NULL ); // unload skybox
return;
}
Q_snprintf( loadname, sizeof( loadname ), "gfx/env/%s", name );
COM_StripExtension( loadname );
// kill the underline suffix to find them manually later
len = Q_strlen( loadname );
if( loadname[len - 1] == '_' )
loadname[len - 1] = '\0';
result = CheckSkybox( loadname, sidenames );
// to prevent infinite recursion if default skybox was missed
if( !result && Q_stricmp( name, DEFAULT_SKYBOX_NAME ))
{
Con_Reportf( S_WARN "missed or incomplete skybox '%s'\n", name );
R_SetupSky( DEFAULT_SKYBOX_NAME ); // force to default
return;
}
ref.dllFuncs.R_SetupSky( NULL ); // unload skybox
Con_DPrintf( "SKY: " );
for( i = 0; i < SKYBOX_MAX_SIDES; i++ )
{
skyboxTextures[i] = ref.dllFuncs.GL_LoadTexture( sidenames[i], NULL, 0, TF_CLAMP|TF_SKY );
if( !skyboxTextures[i] )
break;
Con_DPrintf( "%s%s%s", name, r_skyBoxSuffix[i], i != 5 ? ", " : ". " );
}
if( i == SKYBOX_MAX_SIDES )
{
SetBits( world.flags, FWORLD_CUSTOM_SKYBOX );
Con_DPrintf( "done\n" );
ref.dllFuncs.R_SetupSky( skyboxTextures );
return; // loaded
}
Con_DPrintf( "^2failed\n" );
for( i = 0; i < SKYBOX_MAX_SIDES; i++ )
{
if( skyboxTextures[i] )
ref.dllFuncs.GL_FreeTexture( skyboxTextures[i] );
}
}
/*
================
GL_FreeImage
Frees image by name
================
*/
void GAME_EXPORT GL_FreeImage( const char *name )
{
int texnum;
@@ -171,22 +80,6 @@ static intptr_t pfnEngineGetParm( int parm, int arg )
return CL_RenderGetParm( parm, arg, false ); // prevent recursion
}
static cvar_t *pfnCvar_Get( const char *szName, const char *szValue, int flags, const char *description )
{
return (cvar_t *)Cvar_Get( szName, szValue, flags | FCVAR_REFDLL, description );
}
static void pfnCvar_RegisterVariable( convar_t *var )
{
SetBits( var->flags, FCVAR_REFDLL );
Cvar_RegisterVariable( var );
}
static void pfnCvar_FullSet( const char *var_name, const char *value, int flags )
{
Cvar_FullSet( var_name, value, flags | FCVAR_REFDLL );
}
static void pfnStudioEvent( const mstudioevent_t *event, const cl_entity_t *e )
{
clgame.dllFuncs.pfnStudioEvent( event, e );
@@ -198,7 +91,7 @@ static model_t *pfnGetDefaultSprite( enum ref_defaultsprite_e spr )
{
case REF_DOT_SPRITE: return cl_sprite_dot;
case REF_CHROME_SPRITE: return cl_sprite_shell;
default: Host_Error( "%s: unknown sprite %d\n", __func__, spr );
default: Host_Error( "GetDefaultSprite: unknown sprite %d\n", spr );
}
return NULL;
}
@@ -211,7 +104,7 @@ static void *pfnMod_Extradata( int type, model_t *m )
case mod_studio: return Mod_StudioExtradata( m );
case mod_sprite: // fallthrough
case mod_brush: return NULL;
default: Host_Error( "%s: unknown type %d\n", __func__, type );
default: Host_Error( "Mod_Extradata: unknown type %d\n", type );
}
return NULL;
}
@@ -301,18 +194,18 @@ static qboolean R_Init_Video_( const int type )
return R_Init_Video( type );
}
static const ref_api_t gEngfuncs =
static ref_api_t gEngfuncs =
{
pfnEngineGetParm,
pfnCvar_Get,
(void*)Cvar_Get,
(void*)Cvar_FindVarExt,
Cvar_VariableValue,
Cvar_VariableString,
Cvar_SetValue,
Cvar_Set,
pfnCvar_RegisterVariable,
pfnCvar_FullSet,
Cvar_RegisterVariable,
Cvar_FullSet,
Cmd_AddRefCommand,
Cmd_RemoveCommand,
@@ -447,7 +340,7 @@ static void R_UnloadProgs( void )
Cvar_FullSet( "host_refloaded", "0", FCVAR_READ_ONLY );
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG | FCVAR_REFDLL );
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG );
Cmd_Unlink( CMD_REFDLL );
COM_FreeLibrary( ref.hInstance );
@@ -483,41 +376,48 @@ static void CL_FillTriAPIFromRef( triangleapi_t *dst, const ref_interface_t *src
static qboolean R_LoadProgs( const char *name )
{
extern triangleapi_t gTriApi;
static ref_api_t gpEngfuncs;
REFAPI GetRefAPI; // single export
if( ref.hInstance ) R_UnloadProgs();
FS_AllowDirectPaths( true );
if( !( ref.hInstance = COM_LoadLibrary( name, false, true )))
if( !(ref.hInstance = COM_LoadLibrary( name, false, true ) ))
{
FS_AllowDirectPaths( false );
Con_Reportf( "%s: can't load renderer library %s: %s\n", __func__, name, COM_GetLibraryError() );
Con_Reportf( "R_LoadProgs: can't load renderer library %s: %s\n", name, COM_GetLibraryError() );
return false;
}
FS_AllowDirectPaths( false );
if( !( GetRefAPI = (REFAPI)COM_GetProcAddress( ref.hInstance, GET_REF_API )))
if( !( GetRefAPI = (REFAPI)COM_GetProcAddress( ref.hInstance, GET_REF_API )) )
{
Con_Reportf( "%s: can't find GetRefAPI entry point in %s\n", __func__, name );
COM_FreeLibrary( ref.hInstance );
Con_Reportf( "R_LoadProgs: can't find GetRefAPI entry point in %s\n", name );
ref.hInstance = NULL;
return false;
}
// make local copy of engfuncs to prevent overwrite it with user dll
gpEngfuncs = gEngfuncs;
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
if( GetRefAPI( REF_API_VERSION, &ref.dllFuncs, &gpEngfuncs, &refState ) != REF_API_VERSION )
{
Con_Reportf( "%s: can't init renderer API: wrong version\n", __func__ );
COM_FreeLibrary( ref.hInstance );
Con_Reportf( "R_LoadProgs: can't init renderer API: wrong version\n" );
ref.hInstance = NULL;
return false;
}
refState.developer = host_developer.value;
if( !ref.dllFuncs.R_Init( ))
if( !ref.dllFuncs.R_Init( ) )
{
Con_Reportf( "%s: can't init renderer!\n", __func__ ); //, ref.dllFuncs.R_GetInitError() );
COM_FreeLibrary( ref.hInstance );
Con_Reportf( "R_LoadProgs: can't init renderer!\n" ); //, ref.dllFuncs.R_GetInitError() );
ref.hInstance = NULL;
return false;
}
@@ -554,19 +454,21 @@ static void R_GetRendererName( char *dest, size_t size, const char *opt )
{
if( !Q_strstr( opt, "." OS_LIB_EXT ))
{
const char *format;
#ifdef XASH_INTERNAL_GAMELIBS
#define FMT1 "%s"
#define FMT2 "ref_%s"
#else
#define FMT1 OS_LIB_PREFIX "%s." OS_LIB_EXT
#define FMT2 OS_LIB_PREFIX "ref_%s." OS_LIB_EXT
#endif
if( !Q_strncmp( opt, "ref_", 4 ))
Q_snprintf( dest, size, FMT1, opt );
if( !Q_strcmp( opt, "ref_" ))
format = "%s";
else
Q_snprintf( dest, size, FMT2, opt );
#undef FMT1
#undef FMT2
format = "ref_%s";
#else
if( !Q_strcmp( opt, "ref_" ))
format = OS_LIB_PREFIX "%s." OS_LIB_EXT;
else
format = OS_LIB_PREFIX "ref_%s." OS_LIB_EXT;
#endif
Q_snprintf( dest, size, format, opt );
}
else
{
@@ -663,7 +565,7 @@ static void R_CollectRendererNames( void )
"GL4ES",
#endif
#if XASH_REF_GLES3COMPAT_ENABLED
"GLES3 (gl2_shim)",
"GLES3 (gl2_shim)"
#endif
#if XASH_REF_SOFT_ENABLED
"Software",
@@ -678,8 +580,7 @@ static void R_CollectRendererNames( void )
qboolean R_Init( void )
{
qboolean success = false;
string requested_cmdline;
string requested_cvar;
string requested;
Cvar_RegisterVariable( &gl_vsync );
Cvar_RegisterVariable( &r_showtextures );
@@ -729,16 +630,15 @@ qboolean R_Init( void )
// 1. Command line `-ref` argument.
// 2. `ref_dll` cvar.
// 3. Detected renderers in `DEFAULT_RENDERERS` order.
requested_cmdline[0] = 0;
requested_cvar[0] = 0;
requested[0] = 0;
if( Sys_GetParmFromCmdLine( "-ref", requested_cmdline ))
success = R_LoadRenderer( requested_cmdline );
if( !success && Sys_GetParmFromCmdLine( "-ref", requested ))
success = R_LoadRenderer( requested );
if( !success && COM_CheckString( r_refdll.string ) && Q_stricmp( requested_cmdline, r_refdll.string ))
if( !success && COM_CheckString( r_refdll.string ))
{
Q_strncpy( requested_cvar, r_refdll.string, sizeof( requested_cvar ));
success = R_LoadRenderer( requested_cvar );
Q_strncpy( requested, r_refdll.string, sizeof( requested ));
success = R_LoadRenderer( requested );
}
if( !success )
@@ -748,10 +648,7 @@ qboolean R_Init( void )
for( i = 0; i < ref.numRenderers && !success; i++ )
{
// skip renderer that was requested but failed to load
if( !Q_strcmp( requested_cmdline, ref.shortNames[i] ))
continue;
if( !Q_strcmp( requested_cvar, ref.shortNames[i] ))
if( !Q_strcmp( requested, ref.shortNames[i] ))
continue;
success = R_LoadRenderer( ref.shortNames[i] );
@@ -760,7 +657,7 @@ qboolean R_Init( void )
if( !success )
{
Sys_Error( "Can't initialize any renderer. Check your video drivers!\n" );
Host_Error( "Can't initialize any renderer. Check your video drivers!\n" );
return false;
}

View File

@@ -18,18 +18,19 @@ GNU General Public License for more details.
#include "ref_api.h"
#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ( cl.playernum + 1 ) && e->player )
#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ( cl.playernum + 1 ) && e->player )
struct ref_state_s
{
HINSTANCE hInstance;
qboolean initialized;
int numRenderers;
qboolean initialized;
HINSTANCE hInstance;
ref_interface_t dllFuncs;
// depends on build configuration
const char **shortNames;
const char **readableNames;
int numRenderers;
const char **shortNames;
const char **readableNames;
};
extern struct ref_state_s ref;
@@ -44,14 +45,14 @@ void R_GetTextureParms( int *w, int *h, int texnum );
void GL_RenderFrame( const struct ref_viewpass_s *rvp );
void R_SetupSky( const char *name );
// common engine and renderer cvars
extern convar_t r_decals;
extern convar_t r_adjust_fov;
extern convar_t r_decals;
extern convar_t r_adjust_fov;
extern convar_t gl_clear;
qboolean R_Init( void );
void R_Shutdown( void );
extern triangleapi_t gTriApi;
#endif // REF_COMMON_H

View File

@@ -154,8 +154,7 @@ static const sx_preset_t rgsxpre_hlalpha052[] =
static const sx_preset_t *ptable = rgsxpre;
// cvars
static CVAR_DEFINE_AUTO( dsp_off, "0", FCVAR_ARCHIVE, "disable DSP processing (deprecated)" );
static CVAR_DEFINE_AUTO( room_off, "0", FCVAR_ARCHIVE, "disable DSP processing (GoldSrc compatible cvar)" );
static CVAR_DEFINE_AUTO( dsp_off, "0", FCVAR_ARCHIVE, "disable DSP processing" );
static CVAR_DEFINE_AUTO( dsp_coeff_table, "0", FCVAR_ARCHIVE, "select DSP coefficient table: 0 for release or 1 for alpha 0.52" );
static CVAR_DEFINE_AUTO( room_type, "0", 0, "current room type preset" );
@@ -233,7 +232,6 @@ void SX_Init( void )
sxmod2cur = sxmod2 = 450 * ( idsp_dma_speed / SOUND_11k );
Cvar_RegisterVariable( &dsp_off );
Cvar_RegisterVariable( &room_off );
Cvar_RegisterVariable( &dsp_coeff_table );
Cvar_RegisterVariable( &roomwater_type );
@@ -811,7 +809,7 @@ DSP_Process
*/
void DSP_Process( portable_samplepair_t *pbfront, int sampleCount )
{
if( dsp_off.value || room_off.value || !sampleCount )
if( dsp_off.value || !sampleCount )
return;
// preset is already installed by CheckNewDspPresets
@@ -845,7 +843,7 @@ CheckNewDspPresets
*/
void CheckNewDspPresets( void )
{
if( dsp_off.value || room_off.value )
if( dsp_off.value != 0.0f )
return;
if( FBitSet( dsp_coeff_table.flags, FCVAR_CHANGED ))

View File

@@ -52,11 +52,8 @@ void S_SoundList_f( void )
{
totalSize += sc->size;
if( FBitSet( sc->flags, SOUND_LOOPED ))
Con_Printf( "L" );
else
Con_Printf( " " );
if( sc->loopStart >= 0 ) Con_Printf( "L" );
else Con_Printf( " " );
if( sfx->name[0] == '*' || !Q_strncmp( sfx->name, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ))
Con_Printf( " (%2db) %s : %s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
else Con_Printf( " (%2db) %s : " DEFAULT_SOUNDPATH "%s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
@@ -113,7 +110,7 @@ static wavdata_t *S_CreateDefaultSound( void )
sc->width = 2;
sc->channels = 1;
sc->loopStart = 0;
sc->loopStart = -1;
sc->rate = SOUND_DMA_SPEED;
sc->samples = SOUND_DMA_SPEED;
sc->size = sc->samples * sc->width * sc->channels;
@@ -144,8 +141,8 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
if( Q_stricmp( sfx->name, "*default" ))
{
// load it from disk
if( s_warn_late_precache.value > 0 && cls.state == ca_active )
Con_Printf( S_WARN "%s: late precache of %s\n", __func__, sfx->name );
if( s_warn_late_precache.value > 0 && CL_Active() )
Con_Printf( S_WARN "S_LoadSound: late precache of %s\n", sfx->name );
if( sfx->name[0] == '*' )
sc = FS_LoadSound( sfx->name + 1, NULL, 0 );
@@ -155,11 +152,11 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
if( !sc ) sc = S_CreateDefaultSound();
if( sc->rate < SOUND_11k ) // some bad sounds
Sound_Process( &sc, SOUND_11k, sc->width, sc->channels, SOUND_RESAMPLE );
Sound_Process( &sc, SOUND_11k, sc->width, SOUND_RESAMPLE );
else if( sc->rate > SOUND_11k && sc->rate < SOUND_22k ) // some bad sounds
Sound_Process( &sc, SOUND_22k, sc->width, sc->channels, SOUND_RESAMPLE );
else if( sc->rate > SOUND_22k && sc->rate < SOUND_44k ) // some bad sounds
Sound_Process( &sc, SOUND_44k, sc->width, sc->channels, SOUND_RESAMPLE );
Sound_Process( &sc, SOUND_22k, sc->width, SOUND_RESAMPLE );
else if( sc->rate > SOUND_22k && sc->rate <= SOUND_32k ) // some bad sounds
Sound_Process( &sc, SOUND_44k, sc->width, SOUND_RESAMPLE );
sfx->cache = sc;
@@ -221,7 +218,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache )
sfx = &s_knownSfx[i];
memset( sfx, 0, sizeof( *sfx ));
if( pfInCache ) *pfInCache = false;
Q_strncpy( sfx->name, name, sizeof( sfx->name ));
Q_strncpy( sfx->name, name, MAX_STRING );
sfx->servercount = cl.servercount;
sfx->hashValue = COM_HashKey( sfx->name, MAX_SFX_HASH );
@@ -380,7 +377,7 @@ S_InitSounds
void S_InitSounds( void )
{
// create unused 0-entry
Q_strncpy( s_knownSfx->name, "*default", sizeof( s_knownSfx->name ));
Q_strncpy( s_knownSfx->name, "*default", MAX_QPATH );
s_knownSfx->hashValue = COM_HashKey( s_knownSfx->name, MAX_SFX_HASH );
s_knownSfx->hashNext = s_sfxHashList[s_knownSfx->hashValue];
s_sfxHashList[s_knownSfx->hashValue] = s_knownSfx;

View File

@@ -43,7 +43,7 @@ CVAR_DEFINE_AUTO( s_lerping, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "apply interpo
static CVAR_DEFINE( s_ambient_level, "ambient_level", "0.3", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "volume of environment noises (water and wind)" );
static CVAR_DEFINE( s_ambient_fade, "ambient_fade", "1000", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "rate of volume fading when client is moving" );
static CVAR_DEFINE_AUTO( s_combine_sounds, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "combine channels with same sounds" );
CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "silence the audio when game window loses focus" );
static CVAR_DEFINE_AUTO( snd_mute_losefocus, "1", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "silence the audio when game window loses focus" );
CVAR_DEFINE_AUTO( s_test, "0", 0, "engine developer cvar for quick testing new features" );
CVAR_DEFINE_AUTO( s_samplecount, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "sample count (0 for default value)" );
CVAR_DEFINE_AUTO( s_warn_late_precache, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "warn about late precached sounds on client-side" );
@@ -328,7 +328,7 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean
// don't restart looping sounds for the same entity
wavdata_t *sc = channels[first_to_die].sfx->cache;
if( sc && FBitSet( sc->flags, SOUND_LOOPED ))
if( sc && sc->loopStart != -1 )
{
channel_t *ch = &channels[first_to_die];
@@ -382,7 +382,7 @@ channel_t *SND_PickStaticChannel( const vec3_t pos, sfx_t *sfx )
// no empty slots, alloc a new static sound channel
if( total_channels == MAX_CHANNELS )
{
Con_DPrintf( S_ERROR "%s: no free channels\n", __func__ );
Con_DPrintf( S_ERROR "S_PickStaticChannel: no free channels\n" );
return NULL;
}
@@ -503,7 +503,7 @@ static void SND_Spatialize( channel_t *ch )
pSource = ch->sfx->cache;
if( ch->use_loop && pSource && FBitSet( pSource->flags, SOUND_LOOPED ))
if( ch->use_loop && pSource && pSource->loopStart != -1 )
looping = true;
if( !ch->staticsound )
@@ -524,11 +524,8 @@ static void SND_Spatialize( channel_t *ch )
dist = VectorNormalizeLength( source_vec );
dot = DotProduct( s_listener.right, source_vec );
if( !FBitSet( host.bugcomp, BUGCOMP_SPATIALIZE_SOUND_WITH_ATTN_NONE ))
{
// don't pan sounds with no attenuation
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
}
// don't pan sounds with no attenuation
if( ch->dist_mult <= 0.0f ) dot = 0.0f;
// fill out channel volumes for single location
S_SpatializeChannel( &ch->leftvol, &ch->rightvol, ch->master_vol, gain, dot, dist * ch->dist_mult );
@@ -644,7 +641,7 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
if( !target_chan->leftvol && !target_chan->rightvol )
{
// looping sounds don't use this optimization because they should stick around until they're killed.
if( !sfx->cache || !FBitSet( sfx->cache->flags, SOUND_LOOPED ))
if( !sfx->cache || sfx->cache->loopStart == -1 )
{
// if this is a streaming sound, play the whole thing.
if( chan != CHAN_STREAM )
@@ -896,7 +893,7 @@ int S_GetCurrentStaticSounds( soundlist_t *pout, int size )
VectorCopy( channels[i].origin, pout->origin );
pout->volume = (float)channels[i].master_vol / 255.0f;
pout->attenuation = channels[i].dist_mult * SND_CLIP_DISTANCE;
pout->looping = ( channels[i].use_loop && FBitSet( channels[i].sfx->cache->flags, SOUND_LOOPED ));
pout->looping = ( channels[i].use_loop && channels[i].sfx->cache->loopStart != -1 );
pout->pitch = channels[i].basePitch;
pout->channel = channels[i].entchannel;
pout->wordIndex = channels[i].wordIndex;
@@ -931,7 +928,7 @@ int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
if( !channels[i].sfx || !channels[i].sfx->name[0] || !Q_stricmp( channels[i].sfx->name, "*default" ))
continue; // don't serialize default sounds
looped = ( channels[i].use_loop && FBitSet( channels[i].sfx->cache->flags, SOUND_LOOPED ));
looped = ( channels[i].use_loop && channels[i].sfx->cache->loopStart != -1 );
if( channels[i].entchannel == CHAN_STATIC && looped && !Host_IsQuakeCompatible())
continue; // never serialize static looped sounds. It will be restoring in game code
@@ -1095,7 +1092,7 @@ rawchan_t *S_FindRawChannel( int entnum, qboolean create )
if( !raw_channels[best] )
{
raw_samples = MAX_RAW_SAMPLES;
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * raw_samples );
raw_channels[best] = Mem_Calloc( sndpool, sizeof( *ch ) + sizeof( portable_samplepair_t ) * ( raw_samples - 1 ));
}
ch = raw_channels[best];
@@ -1602,10 +1599,11 @@ void SND_UpdateSound( void )
// release raw-channels that no longer used more than 10 secs
S_FreeIdleRawChannels();
VectorCopy( cl.simvel, s_listener.velocity );
s_listener.frametime = (cl.time - cl.oldtime);
s_listener.waterlevel = cl.local.waterlevel;
s_listener.active = CL_IsInGame();
s_listener.inmenu = cls.key_dest == key_menu;
s_listener.inmenu = CL_IsInMenu();
s_listener.paused = cl.paused;
// update general area ambient sound sources
@@ -1894,7 +1892,7 @@ S_VoiceRecordStart_f
*/
static void S_VoiceRecordStart_f( void )
{
if( cls.state != ca_active )
if( cls.state != ca_active || cls.legacymode )
return;
Voice_RecordStart();

View File

@@ -17,56 +17,30 @@ GNU General Public License for more details.
#include "sound.h"
#include "client.h"
enum
{
IPAINTBUFFER = 0,
IROOMBUFFER,
ISTREAMBUFFER,
CPAINTBUFFERS,
};
#define IPAINTBUFFER 0
#define IROOMBUFFER 1
#define ISTREAMBUFFER 2
enum
{
FILTERTYPE_NONE = 0,
FILTERTYPE_LINEAR,
FILTERTYPE_CUBIC,
};
#define FILTERTYPE_NONE 0
#define FILTERTYPE_LINEAR 1
#define FILTERTYPE_CUBIC 2
#define CCHANVOLUMES 2
#define SND_SCALE_BITS 7
#define SND_SCALE_SHIFT ( 8 - SND_SCALE_BITS )
#define SND_SCALE_LEVELS ( 1 << SND_SCALE_BITS )
#define SND_SCALE_BITS 7
#define SND_SCALE_SHIFT (8 - SND_SCALE_BITS)
#define SND_SCALE_LEVELS (1 << SND_SCALE_BITS)
// sound mixing buffer
#define CPAINTFILTERMEM 3
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
portable_samplepair_t *g_curpaintbuffer;
portable_samplepair_t streambuffer[(PAINTBUFFER_SIZE+1)];
portable_samplepair_t paintbuffer[(PAINTBUFFER_SIZE+1)];
portable_samplepair_t roombuffer[(PAINTBUFFER_SIZE+1)];
portable_samplepair_t facingbuffer[(PAINTBUFFER_SIZE+1)];
portable_samplepair_t temppaintbuffer[(PAINTBUFFER_SIZE+1)];
paintbuffer_t paintbuffers[CPAINTBUFFERS];
// fixed point stuff for real-time resampling
#define FIX_BITS 28
#define FIX_SCALE ( 1 << FIX_BITS )
#define FIX_MASK (( 1 << FIX_BITS ) - 1 )
#define FIX_FLOAT( a ) ((int)(( a ) * FIX_SCALE ))
#define FIX( a ) (((int)( a )) << FIX_BITS )
#define FIX_INTPART( a ) (((int)( a )) >> FIX_BITS )
#define FIX_FRACPART( a ) (( a ) & FIX_MASK )
int snd_scaletable[SND_SCALE_LEVELS][256];
typedef struct
{
qboolean factive; // if true, mix to this paintbuffer using flags
portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing
int ifilter; // current filter memory buffer to use for upsampling pass
portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM];
} paintbuffer_t;
static portable_samplepair_t *g_curpaintbuffer;
static portable_samplepair_t streambuffer[(PAINTBUFFER_SIZE+1)];
static portable_samplepair_t paintbuffer[(PAINTBUFFER_SIZE+1)];
static portable_samplepair_t roombuffer[(PAINTBUFFER_SIZE+1)];
static portable_samplepair_t temppaintbuffer[(PAINTBUFFER_SIZE+1)];
static paintbuffer_t paintbuffers[CPAINTBUFFERS];
static int snd_scaletable[SND_SCALE_LEVELS][256];
void S_InitScaletable( void )
{
int i, j;
@@ -93,7 +67,7 @@ static void S_TransferPaintBuffer( int endtime )
dword *pbuf;
pbuf = (dword *)dma.buffer;
snd_p = (int *)g_curpaintbuffer;
snd_p = (int *)PAINTBUFFER;
lpaintedtime = paintedtime;
sampleMask = ((dma.samples >> 1) - 1);
@@ -137,20 +111,20 @@ static void S_TransferPaintBuffer( int endtime )
//===============================================================================
// Activate a paintbuffer. All active paintbuffers are mixed in parallel within
// MIX_MixChannelsToPaintbuffer, according to flags
static void MIX_ActivatePaintbuffer( int ipaintbuffer )
_inline void MIX_ActivatePaintbuffer( int ipaintbuffer )
{
Assert( ipaintbuffer < CPAINTBUFFERS );
paintbuffers[ipaintbuffer].factive = true;
}
static void MIX_SetCurrentPaintbuffer( int ipaintbuffer )
_inline void MIX_SetCurrentPaintbuffer( int ipaintbuffer )
{
Assert( ipaintbuffer < CPAINTBUFFERS );
g_curpaintbuffer = paintbuffers[ipaintbuffer].pbuf;
Assert( g_curpaintbuffer != NULL );
}
static int MIX_GetCurrentPaintbufferIndex( void )
_inline int MIX_GetCurrentPaintbufferIndex( void )
{
int i;
@@ -162,7 +136,7 @@ static int MIX_GetCurrentPaintbufferIndex( void )
return 0;
}
static paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
_inline paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
{
int ipaint = MIX_GetCurrentPaintbufferIndex();
@@ -171,7 +145,7 @@ static paintbuffer_t *MIX_GetCurrentPaintbufferPtr( void )
}
// Don't mix into any paintbuffers
static void MIX_DeactivateAllPaintbuffers( void )
_inline void MIX_DeactivateAllPaintbuffers( void )
{
int i;
@@ -180,7 +154,7 @@ static void MIX_DeactivateAllPaintbuffers( void )
}
// set upsampling filter indexes back to 0
static void MIX_ResetPaintbufferFilterCounters( void )
_inline void MIX_ResetPaintbufferFilterCounters( void )
{
int i;
@@ -189,13 +163,13 @@ static void MIX_ResetPaintbufferFilterCounters( void )
}
// return pointer to front paintbuffer pbuf, given index
static portable_samplepair_t *MIX_GetPFrontFromIPaint( int ipaintbuffer )
_inline portable_samplepair_t *MIX_GetPFrontFromIPaint( int ipaintbuffer )
{
Assert( ipaintbuffer < CPAINTBUFFERS );
return paintbuffers[ipaintbuffer].pbuf;
}
static paintbuffer_t *MIX_GetPPaintFromIPaint( int ipaint )
_inline paintbuffer_t *MIX_GetPPaintFromIPaint( int ipaint )
{
Assert( ipaint < CPAINTBUFFERS );
return &paintbuffers[ipaint];
@@ -549,7 +523,6 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
wavdata_t *pSource;
int i, sampleCount;
qboolean bZeroVolume;
qboolean local = Host_IsLocalGame();
// mix each channel into paintbuffer
ch = channels;
@@ -576,7 +549,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
{
// play, playvol
}
else if(( s_listener.inmenu || s_listener.paused ) && !ch->localsound && local )
else if(( s_listener.inmenu || s_listener.paused ) && !ch->localsound )
{
// play only local sounds, keep pause for other
continue;
@@ -594,7 +567,6 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
// Don't mix sound data for sounds with zero volume. If it's a non-looping sound,
// just remove the sound when its volume goes to zero.
bZeroVolume = !ch->leftvol && !ch->rightvol;
if( !bZeroVolume )
@@ -604,7 +576,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
bZeroVolume = true;
}
if( !pSource || ( bZeroVolume && !FBitSet( pSource->flags, SOUND_LOOPED )))
if( !pSource || ( bZeroVolume && pSource->loopStart == -1 ))
{
if( !pSource )
{
@@ -657,7 +629,7 @@ static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate
}
// pass in index -1...count+2, return pointer to source sample in either paintbuffer or delay buffer
static portable_samplepair_t *S_GetNextpFilter( int i, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem )
_inline portable_samplepair_t *S_GetNextpFilter( int i, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem )
{
// The delay buffer is assumed to precede the paintbuffer by 6 duplicated samples
if( i == -1 ) return (&(pfiltermem[0]));
@@ -866,14 +838,6 @@ static void MIX_MixPaintbuffers( int ibuf1, int ibuf2, int ibuf3, int count, flo
pbuf2 = paintbuffers[ibuf2].pbuf;
pbuf3 = paintbuffers[ibuf3].pbuf;
if( !gain )
{
// do not mix buf2 into buf3, just copy
if( pbuf1 != pbuf3 )
memcpy( pbuf3, pbuf1, sizeof( *pbuf1 ) * count );
return;
}
// destination buffer stereo - average n chans down to stereo
// destination 2ch:
@@ -923,7 +887,7 @@ static void S_MixUpsample( int sampleCount, int filtertype )
static void MIX_MixRawSamplesBuffer( int end )
{
portable_samplepair_t *pbuf, *roombuf, *streambuf;
uint i, j, stop;
uint i, j, stop;
roombuf = MIX_GetPFrontFromIPaint( IROOMBUFFER );
streambuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
@@ -956,11 +920,7 @@ static void MIX_MixRawSamplesBuffer( int end )
}
if( ch->entnum > 0 )
{
int pos = paintedtime & ( ch->max_samples - 1 );
SND_MoveMouthRaw( ch, &ch->rawsamples[pos], bound( 0, ch->max_samples - pos, stop - paintedtime ));
}
SND_MoveMouthRaw( ch, &ch->rawsamples[paintedtime & ( ch->max_samples - 1 )], stop - paintedtime );
}
}

View File

@@ -57,12 +57,6 @@ float S_GetMusicVolume( void )
{
float scale = 1.0f;
if( host.status == HOST_NOFOCUS && snd_mute_losefocus.value != 0.0f )
{
// we return zero volume to keep sounds running
return 0.0f;
}
if( !s_listener.inmenu && musicfade.percent != 0 )
{
scale = bound( 0.0f, musicfade.percent / 100.0f, 1.0f );
@@ -148,7 +142,7 @@ S_StreamGetCurrentState
save\restore code
=================
*/
qboolean S_StreamGetCurrentState( char *currentTrack, size_t currentTrackSize, char *loopTrack, size_t loopTrackSize, int *position )
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position )
{
if( !s_bgTrack.stream )
return false; // not active
@@ -156,15 +150,15 @@ qboolean S_StreamGetCurrentState( char *currentTrack, size_t currentTrackSize, c
if( currentTrack )
{
if( s_bgTrack.current[0] )
Q_strncpy( currentTrack, s_bgTrack.current, currentTrackSize );
else Q_strncpy( currentTrack, "*", currentTrackSize ); // no track
Q_strncpy( currentTrack, s_bgTrack.current, MAX_STRING );
else Q_strncpy( currentTrack, "*", MAX_STRING ); // no track
}
if( loopTrack )
{
if( s_bgTrack.loopName[0] )
Q_strncpy( loopTrack, s_bgTrack.loopName, loopTrackSize );
else Q_strncpy( loopTrack, "*", loopTrackSize ); // no track
Q_strncpy( loopTrack, s_bgTrack.loopName, MAX_STRING );
else Q_strncpy( loopTrack, "*", MAX_STRING ); // no track
}
if( position )

View File

@@ -27,7 +27,7 @@ int S_ConvertLoopedPosition( wavdata_t *pSource, int samplePosition, qboolean us
// convert to a position within the loop
// At the end of the loop, we return a short buffer, and subsequent call
// will loop back and get the rest of the buffer
if( FBitSet( pSource->flags, SOUND_LOOPED ) && samplePosition >= pSource->samples && use_loop )
if( pSource->loopStart >= 0 && samplePosition >= pSource->samples && use_loop )
{
// size of loop
int loopSize = pSource->samples - pSource->loopStart;

View File

@@ -96,7 +96,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
if( width == 1 )
{
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * ( end - 1 )];
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * end];
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
{
@@ -109,7 +109,7 @@ static int S_TrimEnd( const wavdata_t *wav, int end )
}
else if( width == 2 )
{
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * ( end - 1 )];
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * end];
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
{
@@ -248,12 +248,6 @@ static const char *VOX_GetDirectory( char *szpath, const char *psz, int nsize )
const char *p;
int len;
// HACKHACK: some modders send strings like "/fvox/_period four"
// which should get parsed as "_period four" said by fvox
// it might be incorrect but ignore first slash here for now
if( psz[0] == '/' )
psz++;
// search / backwards
p = Q_strrchr( psz, '/' );
@@ -267,7 +261,7 @@ static const char *VOX_GetDirectory( char *szpath, const char *psz, int nsize )
if( len > nsize )
{
Con_Printf( "%s: invalid directory in: %s\n", __func__, psz );
Con_Printf( "VOX_GetDirectory: invalid directory in: %s\n", psz );
return NULL;
}
@@ -473,7 +467,7 @@ void VOX_LoadSound( channel_t *ch, const char *pszin )
if( !psz )
{
Con_Printf( "%s: no sentence named %s\n", __func__, pszin );
Con_Printf( "VOX_LoadSound: no sentence named %s\n", pszin );
return;
}
@@ -481,13 +475,13 @@ void VOX_LoadSound( channel_t *ch, const char *pszin )
if( !psz )
{
Con_Printf( "%s: failed getting directory for %s\n", __func__, pszin );
Con_Printf( "VOX_LoadSound: failed getting directory for %s\n", pszin );
return;
}
if( Q_strlen( psz ) >= sizeof( buffer ) )
{
Con_Printf( "%s: sentence is too long %s", __func__, psz );
Con_Printf( "VOX_LoadSound: sentence is too long %s", psz );
return;
}
@@ -601,8 +595,8 @@ static void Test_VOX_GetDirectory( void )
{
"", "", "vox/",
"bark bark", "bark bark", "vox/",
"barney/meow", "meow", "barney/",
"/fvox/_period", "_period", "fvox/",
"barney/meow", "meow", "barney/"
};
int i;

View File

@@ -20,181 +20,208 @@ extern poolhandle_t sndpool;
#include "xash3d_mathlib.h"
#define XASH_AUDIO_CD_QUALITY 1 // some platforms might need this
// sound engine rate defines
#if XASH_AUDIO_CD_QUALITY
#define SOUND_11k 11025 // 11khz sample rate
#define SOUND_22k 22050 // 22khz sample rate
#define SOUND_44k 44100 // 44khz sample rate
#else // XASH_AUDIO_CD_QUALITY
#define SOUND_11k 12000 // 11khz sample rate
#define SOUND_22k 24000 // 22khz sample rate
#define SOUND_44k 48000 // 44khz sample rate
#endif // XASH_AUDIO_CD_QUALITY
#define SOUND_DMA_SPEED 44100 // hardware playback rate
#define SOUND_11k 11025 // 11khz sample rate
#define SOUND_16k 16000 // 16khz sample rate
#define SOUND_22k 22050 // 22khz sample rate
#define SOUND_32k 32000 // 32khz sample rate
#define SOUND_44k 44100 // 44khz sample rate
#define DMA_MSEC_PER_SAMPLE ((float)(1000.0 / SOUND_DMA_SPEED))
#define SOUND_DMA_SPEED SOUND_44k // hardware playback rate
// fixed point stuff for real-time resampling
#define FIX_BITS 28
#define FIX_SCALE (1 << FIX_BITS)
#define FIX_MASK ((1 << FIX_BITS)-1)
#define FIX_FLOAT(a) ((int)((a) * FIX_SCALE))
#define FIX(a) (((int)(a)) << FIX_BITS)
#define FIX_INTPART(a) (((int)(a)) >> FIX_BITS)
#define FIX_FRACTION(a,b) (FIX(a)/(b))
#define FIX_FRACPART(a) ((a) & FIX_MASK)
// NOTE: clipped sound at 32760 to avoid overload
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
#define CLIP( x ) (( x ) > 32760 ? 32760 : (( x ) < -32760 ? -32760 : ( x )))
#define PAINTBUFFER_SIZE 1024 // 44k: was 512
#define PAINTBUFFER_SIZE 1024 // 44k: was 512
#define PAINTBUFFER (g_curpaintbuffer)
#define CPAINTBUFFERS 3
#define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed
#define S_RAW_SOUND_BACKGROUNDTRACK -2
#define S_RAW_SOUND_SOUNDTRACK -1
#define S_RAW_SAMPLES_PRECISION_BITS 14
// sound mixing buffer
#define CPAINTFILTERMEM 3
#define CPAINTFILTERS 4 // maximum number of consecutive upsample passes per paintbuffer
#define S_RAW_SOUND_IDLE_SEC 10 // time interval for idling raw sound before it's freed
#define S_RAW_SOUND_BACKGROUNDTRACK -2
#define S_RAW_SOUND_SOUNDTRACK -1
#define S_RAW_SAMPLES_PRECISION_BITS 14
#define CIN_FRAMETIME (1.0f / 30.0f)
typedef struct
{
int left;
int right;
int left;
int right;
} portable_samplepair_t;
typedef struct
{
qboolean factive; // if true, mix to this paintbuffer using flags
portable_samplepair_t *pbuf; // front stereo mix buffer, for 2 or 4 channel mixing
int ifilter; // current filter memory buffer to use for upsampling pass
portable_samplepair_t fltmem[CPAINTFILTERS][CPAINTFILTERMEM];
} paintbuffer_t;
typedef struct sfx_s
{
char name[MAX_QPATH];
wavdata_t *cache;
char name[MAX_QPATH];
wavdata_t *cache;
int servercount;
uint hashValue;
struct sfx_s *hashNext;
int servercount;
uint hashValue;
struct sfx_s *hashNext;
} sfx_t;
extern portable_samplepair_t paintbuffer[];
extern portable_samplepair_t roombuffer[];
extern portable_samplepair_t temppaintbuffer[];
extern portable_samplepair_t *g_curpaintbuffer;
extern paintbuffer_t paintbuffers[];
// structure used for fading in and out client sound volume.
typedef struct
{
float initial_percent;
float percent; // how far to adjust client's volume down by.
float starttime; // GetHostTime() when we started adjusting volume
float fadeouttime; // # of seconds to get to faded out state
float holdtime; // # of seconds to hold
float fadeintime; // # of seconds to restore
float initial_percent;
float percent; // how far to adjust client's volume down by.
float starttime; // GetHostTime() when we started adjusting volume
float fadeouttime; // # of seconds to get to faded out state
float holdtime; // # of seconds to hold
float fadeintime; // # of seconds to restore
} soundfade_t;
typedef struct
{
float percent;
float percent;
} musicfade_t;
typedef struct snd_format_s
{
uint speed;
byte width;
byte channels;
unsigned int speed;
unsigned int width;
unsigned int channels;
} snd_format_t;
typedef struct
{
snd_format_t format;
int samples; // mono samples in buffer
int samplepos; // in mono samples
qboolean initialized; // sound engine is active
byte *buffer;
const char *backendName;
snd_format_t format;
int samples; // mono samples in buffer
int samplepos; // in mono samples
byte *buffer;
qboolean initialized; // sound engine is active
const char *backendName;
} dma_t;
#include "vox.h"
typedef struct
{
double sample;
wavdata_t *pData;
double forcedEndSample;
qboolean finished;
double sample;
wavdata_t *pData;
double forcedEndSample;
qboolean finished;
} mixer_t;
typedef struct rawchan_s
{
int entnum;
int master_vol;
int leftvol; // 0-255 left volume
int rightvol; // 0-255 right volume
float dist_mult; // distance multiplier (attenuation/clipK)
vec3_t origin; // only use if fixed_origin is set
volatile uint s_rawend;
float oldtime; // catch time jumps
wavdata_t sound_info; // advance play position
size_t max_samples; // buffer length
portable_samplepair_t rawsamples[]; // variable sized
int entnum;
int master_vol;
int leftvol; // 0-255 left volume
int rightvol; // 0-255 right volume
float dist_mult; // distance multiplier (attenuation/clipK)
vec3_t origin; // only use if fixed_origin is set
volatile uint s_rawend;
wavdata_t sound_info; // advance play position
float oldtime; // catch time jumps
size_t max_samples; // buffer length
portable_samplepair_t rawsamples[1]; // variable sized
} rawchan_t;
typedef struct channel_s
{
char name[16]; // keep sentence name
sfx_t *sfx; // sfx number
char name[16]; // keept sentence name
sfx_t *sfx; // sfx number
int leftvol; // 0-255 left volume
int rightvol; // 0-255 right volume
int leftvol; // 0-255 left volume
int rightvol; // 0-255 right volume
int entnum; // entity soundsource
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
vec3_t origin; // only use if fixed_origin is set
float dist_mult; // distance multiplier (attenuation/clipK)
int master_vol; // 0-255 master volume
int basePitch; // base pitch percent (100% is normal pitch playback)
float pitch; // real-time pitch after any modulation or shift by dynamic data
qboolean use_loop; // don't loop default and local sounds
qboolean staticsound; // use origin instead of fetching entnum's origin
qboolean localsound; // it's a local menu sound (not looped, not paused)
mixer_t pMixer;
int entnum; // entity soundsource
int entchannel; // sound channel (CHAN_STREAM, CHAN_VOICE, etc.)
vec3_t origin; // only use if fixed_origin is set
float dist_mult; // distance multiplier (attenuation/clipK)
int master_vol; // 0-255 master volume
qboolean isSentence; // bit who indicated sentence
int basePitch; // base pitch percent (100% is normal pitch playback)
float pitch; // real-time pitch after any modulation or shift by dynamic data
qboolean use_loop; // don't loop default and local sounds
qboolean staticsound; // use origin instead of fetching entnum's origin
qboolean localsound; // it's a local menu sound (not looped, not paused)
mixer_t pMixer;
// sentence mixer
qboolean isSentence; // bit indicating sentence
int wordIndex;
mixer_t *currentWord; // NULL if sentence is finished
voxword_t words[CVOXWORDMAX];
int wordIndex;
mixer_t *currentWord; // NULL if sentence is finished
voxword_t words[CVOXWORDMAX];
} channel_t;
typedef struct
{
vec3_t origin; // simorg + view_ofs
vec3_t forward;
vec3_t right;
vec3_t up;
vec3_t origin; // simorg + view_ofs
vec3_t velocity;
vec3_t forward;
vec3_t right;
vec3_t up;
int entnum;
int waterlevel;
float frametime; // used for sound fade
qboolean active;
qboolean inmenu; // listener in-menu ?
qboolean paused;
qboolean streaming; // playing AVI-file
qboolean stream_paused; // pause only background track
int entnum;
int waterlevel;
float frametime; // used for sound fade
qboolean active;
qboolean inmenu; // listener in-menu ?
qboolean paused;
qboolean streaming; // playing AVI-file
qboolean stream_paused; // pause only background track
} listener_t;
typedef struct
{
string current; // a currently playing track
string loopName; // may be empty
stream_t *stream;
int source; // may be game, menu, etc
string current; // a currently playing track
string loopName; // may be empty
stream_t *stream;
int source; // may be game, menu, etc
} bg_track_t;
//====================================================================
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
#define MAX_RAW_CHANNELS 48
#define MAX_RAW_SAMPLES 8192
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
#define MAX_RAW_CHANNELS 48
#define MAX_RAW_SAMPLES 8192
extern sound_t ambient_sfx[NUM_AMBIENTS];
extern qboolean snd_ambient;
extern channel_t channels[MAX_CHANNELS];
extern rawchan_t *raw_channels[MAX_RAW_CHANNELS];
extern int total_channels;
extern int paintedtime;
extern int soundtime;
extern listener_t s_listener;
extern int idsp_room;
extern dma_t dma;
extern sound_t ambient_sfx[NUM_AMBIENTS];
extern qboolean snd_ambient;
extern channel_t channels[MAX_CHANNELS];
extern rawchan_t *raw_channels[MAX_RAW_CHANNELS];
extern int total_channels;
extern int paintedtime;
extern int soundtime;
extern listener_t s_listener;
extern int idsp_room;
extern dma_t dma;
extern convar_t s_musicvolume;
extern convar_t s_lerping;
extern convar_t s_test; // cvar to test new effects
extern convar_t s_musicvolume;
extern convar_t s_lerping;
extern convar_t s_test; // cvar to testify new effects
extern convar_t s_samplecount;
extern convar_t s_warn_late_precache;
extern convar_t snd_mute_losefocus;
void S_InitScaletable( void );
wavdata_t *S_LoadSound( sfx_t *sfx );
@@ -265,6 +292,7 @@ void SND_ForceCloseMouth( int entnum );
//
void S_StreamSoundTrack( void );
void S_StreamBackgroundTrack( void );
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
void S_PrintBackgroundTrackState( void );
void S_FadeMusicVolume( float fadePercent );

View File

@@ -250,7 +250,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
if( IsEndOfText( trim ))
{
Con_Reportf( "%s: unexpected '}' found, line %d\n", __func__, lineNumber );
Con_Reportf( "TextMessage: unexpected '}' found, line %d\n", lineNumber );
return;
}
Q_strncpy( currentName, trim, sizeof( currentName ));
@@ -263,7 +263,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
// save name on name heap
if( lastNamePos + length > 32768 )
{
Con_Reportf( "%s: error while parsing!\n", __func__ );
Con_Reportf( "TextMessage: error while parsing!\n" );
return;
}
@@ -286,7 +286,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
}
if( IsStartOfText( trim ))
{
Con_Reportf( "%s: unexpected '{' found, line %d\n", __func__, lineNumber );
Con_Reportf( "TextMessage: unexpected '{' found, line %d\n", lineNumber );
return;
}
break;
@@ -302,7 +302,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
}
}
Con_Reportf( "%s: parsed %d text messages\n", __func__, messageCount );
Con_Reportf( "TextMessage: parsed %d text messages\n", messageCount );
nameHeapSize = lastNamePos;
textHeapSize = 0;
@@ -347,7 +347,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
}
if(( pCurrentText - (char *)clgame.titles ) != ( textHeapSize + nameHeapSize + messageSize ))
Con_DPrintf( S_ERROR "%s: overflow text message buffer!\n", __func__ );
Con_DPrintf( S_ERROR "TextMessage: overflow text message buffer!\n" );
clgame.numTitles = messageCount;
}

View File

@@ -23,182 +23,55 @@ GNU General Public License for more details.
#include "input.h"
#include "platform/platform.h"
#define VGUI_MAX_TEXTURES 1024
CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support for vgui text" );
typedef struct vgui_static_s
static void GAME_EXPORT *VGUI_EngineMalloc( size_t size );
static void GAME_EXPORT VGUI_GetMousePos( int *, int * );
static void GAME_EXPORT VGUI_CursorSelect( VGUI_DefaultCursor );
static byte GAME_EXPORT VGUI_GetColor( int, int );
static int GAME_EXPORT VGUI_UtfProcessChar( int in );
static qboolean GAME_EXPORT VGUI_IsInGame( void );
static struct
{
qboolean initialized;
VGUI_DefaultCursor cursor;
vguiapi_t dllFuncs;
int textures[VGUI_MAX_TEXTURES];
int texture_id;
int bound_texture;
byte color[4];
qboolean enable_texture;
VGUI_DefaultCursor cursor;
HINSTANCE hInstance;
enum VGUI_KeyCode virtualKeyTrans[256];
} vgui_static_t;
static vgui_static_t vgui = {
false, -1
} vgui =
{
false,
{
false, // Not initialized yet
NULL, // VGUI_DrawInit,
NULL, // VGUI_DrawShutdown,
NULL, // VGUI_SetupDrawingText,
NULL, // VGUI_SetupDrawingRect,
NULL, // VGUI_SetupDrawingImage,
NULL, // VGUI_BindTexture,
NULL, // VGUI_EnableTexture,
NULL, // VGUI_CreateTexture,
NULL, // VGUI_UploadTexture,
NULL, // VGUI_UploadTextureBlock,
NULL, // VGUI_DrawQuad,
NULL, // VGUI_GetTextureSizes,
NULL, // VGUI_GenerateTexture,
VGUI_EngineMalloc,
VGUI_CursorSelect,
VGUI_GetColor,
VGUI_IsInGame,
Key_EnableTextInput,
VGUI_GetMousePos,
VGUI_UtfProcessChar,
Platform_GetClipboardText,
Platform_SetClipboardText,
Platform_GetKeyModifiers,
},
-1
};
static CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support for vgui text" );
static void GAME_EXPORT VGUI_DrawInit( void )
{
memset( vgui.textures, 0, sizeof( vgui.textures ));
memset( vgui.color, 0, sizeof( vgui.color ));
vgui.texture_id = vgui.bound_texture = 0;
vgui.enable_texture = true;
}
static void GAME_EXPORT VGUI_DrawShutdown( void )
{
int i;
for( i = 1; i < vgui.texture_id; i++ )
ref.dllFuncs.GL_FreeTexture( vgui.textures[i] );
}
static int GAME_EXPORT VGUI_GenerateTexture( void )
{
if( ++vgui.texture_id >= VGUI_MAX_TEXTURES )
Host_Error( "%s: VGUI_MAX_TEXTURES limit exceeded\n", __func__ );
return vgui.texture_id;
}
static void GAME_EXPORT VGUI_UploadTexture( int id, const char *buffer, int width, int height )
{
rgbdata_t r_image = { 0 };
char texName[32];
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
{
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
return;
}
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
r_image.width = width;
r_image.height = height;
r_image.type = PF_RGBA_32;
r_image.size = width * height * 4;
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
r_image.buffer = (byte*)buffer;
vgui.textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE );
}
static void GAME_EXPORT VGUI_CreateTexture( int id, int width, int height )
{
rgbdata_t r_image = { 0 };
char texName[32];
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
{
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
return;
}
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
r_image.width = width;
r_image.height = height;
r_image.type = PF_RGBA_32;
r_image.size = width * height * 4;
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
r_image.buffer = NULL;
vgui.textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE );
vgui.bound_texture = id;
}
static void GAME_EXPORT VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight )
{
if( id <= 0 || id >= VGUI_MAX_TEXTURES || vgui.textures[id] == 0 )
{
Con_DPrintf( S_ERROR "%s: bad texture %i. Ignored\n", __func__, id );
return;
}
ref.dllFuncs.VGUI_UploadTextureBlock( drawX, drawY, rgba, blockWidth, blockHeight );
vgui.bound_texture = id;
}
static void GAME_EXPORT VGUI_BindTexture( int id )
{
if( id <= 0 || id >= VGUI_MAX_TEXTURES || !vgui.textures[id] )
id = 1; // NOTE: same as bogus index 2700 in GoldSrc
ref.dllFuncs.GL_Bind( XASH_TEXTURE0, vgui.textures[id] );
vgui.bound_texture = id;
}
static void GAME_EXPORT VGUI_GetTextureSizes( int *w, int *h )
{
int texnum;
if( vgui.bound_texture )
texnum = vgui.textures[vgui.bound_texture];
else
texnum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
R_GetTextureParms( w, h, texnum );
}
static void GAME_EXPORT VGUI_SetupDrawingRect( int *pColor )
{
ref.dllFuncs.VGUI_SetupDrawing( true );
Vector4Set( vgui.color, pColor[0], pColor[1], pColor[2], 255 - pColor[3] );
}
static void GAME_EXPORT VGUI_SetupDrawingText( int *pColor )
{
ref.dllFuncs.VGUI_SetupDrawing( false );
Vector4Set( vgui.color, pColor[0], pColor[1], pColor[2], 255 - pColor[3] );
}
static void GAME_EXPORT VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr )
{
float x, y, w, h;
if( !ul || !lr )
return;
x = ul->point[0];
y = ul->point[1];
w = lr->point[0] - x;
h = lr->point[1] - y;
SPR_AdjustSize( &x, &y, &w, &h );
if( vgui.enable_texture )
{
float s1, s2, t1, t2;
s1 = ul->coord[0];
t1 = ul->coord[1];
s2 = lr->coord[0];
t2 = lr->coord[1];
ref.dllFuncs.Color4ub( vgui.color[0], vgui.color[1], vgui.color[2], vgui.color[3] );
ref.dllFuncs.R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, vgui.textures[vgui.bound_texture] );
}
else
{
ref.dllFuncs.FillRGBABlend( x, y, w, h, vgui.color[0], vgui.color[1], vgui.color[2], vgui.color[3] );
}
}
static void GAME_EXPORT VGUI_EnableTexture( qboolean enable )
{
vgui.enable_texture = enable;
}
static void GAME_EXPORT *VGUI_EngineMalloc( size_t size )
{
@@ -244,46 +117,33 @@ qboolean VGui_IsActive( void )
return vgui.initialized;
}
static void VGui_FillAPIFromRef( vguiapi_t *to, const ref_interface_t *from )
{
to->DrawInit = from->VGUI_DrawInit;
to->DrawShutdown = from->VGUI_DrawShutdown;
to->SetupDrawingText = from->VGUI_SetupDrawingText;
to->SetupDrawingRect = from->VGUI_SetupDrawingRect;
to->SetupDrawingImage = from->VGUI_SetupDrawingImage;
to->BindTexture = from->VGUI_BindTexture;
to->EnableTexture = from->VGUI_EnableTexture;
to->CreateTexture = from->VGUI_CreateTexture;
to->UploadTexture = from->VGUI_UploadTexture;
to->UploadTextureBlock = from->VGUI_UploadTextureBlock;
to->DrawQuad = from->VGUI_DrawQuad;
to->GetTextureSizes = from->VGUI_GetTextureSizes;
to->GenerateTexture = from->VGUI_GenerateTexture;
}
void VGui_RegisterCvars( void )
{
Cvar_RegisterVariable( &vgui_utf8 );
}
static const vguiapi_t gEngfuncs =
{
false, // Not initialized yet
VGUI_DrawInit, // VGUI_DrawInit,
VGUI_DrawShutdown, // VGUI_DrawShutdown,
VGUI_SetupDrawingText, // VGUI_SetupDrawingText,
VGUI_SetupDrawingRect, // VGUI_SetupDrawingRect,
VGUI_SetupDrawingText, // VGUI_SetupDrawingImage, (same as text)
VGUI_BindTexture, // VGUI_BindTexture,
VGUI_EnableTexture, // VGUI_EnableTexture,
VGUI_CreateTexture, // VGUI_CreateTexture,
VGUI_UploadTexture, // VGUI_UploadTexture,
VGUI_UploadTextureBlock, // VGUI_UploadTextureBlock,
VGUI_DrawQuad, // VGUI_DrawQuad,
VGUI_GetTextureSizes, // VGUI_GetTextureSizes,
VGUI_GenerateTexture, // VGUI_GenerateTexture,
VGUI_EngineMalloc,
VGUI_CursorSelect,
VGUI_GetColor,
VGUI_IsInGame,
Key_EnableTextInput,
VGUI_GetMousePos,
VGUI_UtfProcessChar,
Platform_GetClipboardText,
Platform_SetClipboardText,
Platform_GetKeyModifiers,
};
qboolean VGui_LoadProgs( HINSTANCE hInstance )
{
void (*F)( vguiapi_t* );
qboolean client = hInstance != NULL;
vgui.dllFuncs = gEngfuncs;
// not loading interface from client.dll, load vgui_support.dll instead
if( !client )
{
@@ -307,7 +167,7 @@ qboolean VGui_LoadProgs( HINSTANCE hInstance )
{
if( FS_FileExists( vguiloader, false ))
Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() );
else Con_Reportf( "%s: not found\n", __func__ );
else Con_Reportf( "vgui_support: not found\n" );
return false;
}
@@ -318,15 +178,16 @@ qboolean VGui_LoadProgs( HINSTANCE hInstance )
if( F )
{
VGui_FillAPIFromRef( &vgui.dllFuncs, &ref.dllFuncs );
F( &vgui.dllFuncs );
vgui.initialized = vgui.dllFuncs.initialized = true;
Con_Reportf( "%s: initialized legacy API in %s module\n", __func__, client ? "client" : "support" );
Con_Reportf( "vgui_support: initialized legacy API in %s module\n", client ? "client" : "support" );
return true;
}
Con_Reportf( S_ERROR "%s: Failed to find VGUI support API entry point in %s module\n", __func__, client ? "client" : "support" );
Con_Reportf( S_ERROR "Failed to find VGUI support API entry point in %s module\n", client ? "client" : "support" );
return false;
}
@@ -372,9 +233,8 @@ void VGui_Shutdown( void )
if( vgui.hInstance )
COM_FreeLibrary( vgui.hInstance );
// drop pointers to now unloaded vgui_support
vgui.dllFuncs = gEngfuncs;
vgui.hInstance = NULL;
vgui.initialized = false;
}

View File

@@ -26,7 +26,7 @@ static CVAR_DEFINE_AUTO( vid_scale, "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "p
CVAR_DEFINE_AUTO( vid_highdpi, "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" );
CVAR_DEFINE_AUTO( vid_maximized, "0", FCVAR_RENDERINFO, "window maximized state, read-only" );
CVAR_DEFINE( vid_fullscreen, "fullscreen", DEFAULT_FULLSCREEN, FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
CVAR_DEFINE( vid_fullscreen, "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
CVAR_DEFINE( window_width, "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
CVAR_DEFINE( window_height, "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
CVAR_DEFINE( window_xpos, "_window_xpos", "-1", FCVAR_RENDERINFO, "window position by horizontal" );
@@ -175,7 +175,7 @@ static void VID_Mode_f( void )
vidmode = R_GetVideoMode( Q_atoi( Cmd_Argv( 1 )) );
if( !vidmode )
{
Con_Printf( S_ERROR "unable to set mode, backend returned null" );
Con_Print( S_ERROR "unable to set mode, backend returned null" );
return;
}

View File

@@ -25,17 +25,11 @@ voice_state_t voice = { 0 };
CVAR_DEFINE_AUTO( voice_enable, "1", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "enable voice chat" );
CVAR_DEFINE_AUTO( voice_loopback, "0", FCVAR_PRIVILEGED, "loopback voice back to the speaker" );
CVAR_DEFINE_AUTO( voice_scale, "1.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "incoming voice volume scale" );
CVAR_DEFINE_AUTO( voice_transmit_scale, "1.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "outcoming voice volume scale" );
CVAR_DEFINE_AUTO( voice_avggain, "0.5", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (average)" );
CVAR_DEFINE_AUTO( voice_maxgain, "5.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (maximum)" );
CVAR_DEFINE_AUTO( voice_inputfromfile, "0", FCVAR_PRIVILEGED, "input voice from voice_input.wav" );
static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale );
// in case user enabled voice after connection
// can't keep in `voice` struct because it gets zeroed on shutdown
static string voice_codec_init;
static int voice_quality_init;
static void Voice_ApplyGainAdjust( int16_t *samples, int count );
/*
===============================================================================
@@ -45,25 +39,6 @@ static int voice_quality_init;
===============================================================================
*/
static qboolean Voice_InitCustomMode( void )
{
int err = 0;
voice.width = sizeof( opus_int16 );
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
if( !voice.custom_mode )
{
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err ));
return false;
}
return true;
}
/*
=========================
Voice_InitOpusDecoder
@@ -72,17 +47,24 @@ Voice_InitOpusDecoder
*/
static qboolean Voice_InitOpusDecoder( void )
{
int err = 0;
int err;
for( int i = 0; i < cl.maxclients; i++ )
voice.width = sizeof( opus_int16 );
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
if( !voice.custom_mode )
{
voice.decoders[i] = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err ));
return false;
}
if( !voice.decoders[i] )
{
Con_Printf( S_ERROR "Can't create Opus decoder for %i: %s\n", i, opus_strerror( err ));
return false;
}
voice.decoder = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
if( !voice.decoder )
{
Con_Printf( S_ERROR "Can't create Opus encoder: %s\n", opus_strerror( err ));
return false;
}
return true;
@@ -96,7 +78,7 @@ Voice_InitOpusEncoder
*/
static qboolean Voice_InitOpusEncoder( int quality )
{
int err = 0;
int err;
voice.encoder = opus_custom_encoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
if( !voice.encoder )
@@ -135,13 +117,10 @@ Voice_ShutdownOpusDecoder
*/
static void Voice_ShutdownOpusDecoder( void )
{
for( int i = 0; i < MAX_CLIENTS; i++ )
if( voice.decoder )
{
if( !voice.decoders[i] )
continue;
opus_custom_decoder_destroy( voice.decoders[i] );
voice.decoders[i] = NULL;
opus_custom_decoder_destroy( voice.decoder );
voice.decoder = NULL;
}
}
@@ -158,10 +137,7 @@ static void Voice_ShutdownOpusEncoder( void )
opus_custom_encoder_destroy( voice.encoder );
voice.encoder = NULL;
}
}
static void Voice_ShutdownCustomMode( void )
{
if( voice.custom_mode )
{
opus_custom_mode_destroy( voice.custom_mode );
@@ -208,7 +184,7 @@ static uint Voice_GetOpusCompressedData( byte *out, uint maxsize, uint *frames )
if( !voice.input_file )
{
// adjust gain before encoding, but only for input from voice
Voice_ApplyGainAdjust((opus_int16*)(voice.input_buffer + ofs), voice.frame_size, voice_transmit_scale.value);
Voice_ApplyGainAdjust((opus_int16*)(voice.input_buffer + ofs), voice.frame_size);
}
#endif
@@ -262,10 +238,10 @@ Voice_ApplyGainAdjust
=========================
*/
static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale )
static void Voice_ApplyGainAdjust( int16_t *samples, int count )
{
float gain, modifiedMax;
int average, blockOffset = 0;
int average, adjustedSample, blockOffset = 0;
for( ;; )
{
@@ -284,8 +260,10 @@ static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale )
localMax = absSample;
localSum += absSample;
gain = voice.autogain.current_gain + i * voice.autogain.gain_multiplier;
samples[blockOffset + i] = bound( SHRT_MIN, (int)( sample * gain ), SHRT_MAX );
adjustedSample = Q_min( SHRT_MAX, Q_max(( int )( sample * gain ), SHRT_MIN ));
samples[blockOffset + i] = adjustedSample;
}
if( blockOffset % voice.autogain.block_size == 0 )
@@ -293,9 +271,9 @@ static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale )
average = localSum / blockSize;
modifiedMax = average + ( localMax - average ) * voice_avggain.value;
voice.autogain.current_gain = voice.autogain.next_gain * scale;
voice.autogain.next_gain = Q_min( (float)SHRT_MAX / modifiedMax, voice_maxgain.value ) * scale;
voice.autogain.gain_multiplier = ( voice.autogain.next_gain - voice.autogain.current_gain ) / ( blockSize - 1 );
voice.autogain.current_gain = voice.autogain.next_gain * voice_scale.value;
voice.autogain.next_gain = Q_min( (float)SHRT_MAX / modifiedMax, voice_maxgain.value ) * voice_scale.value;
voice.autogain.gain_multiplier = ( voice.autogain.next_gain - voice.autogain.current_gain ) / ( voice.autogain.block_size - 1 );
}
blockOffset += blockSize;
}
@@ -396,16 +374,13 @@ void Voice_RecordStart( void )
{
Voice_RecordStop();
if( !voice.initialized )
return;
if( voice_inputfromfile.value )
{
voice.input_file = FS_LoadSound( "voice_input.wav", NULL, 0 );
if( voice.input_file )
{
Sound_Process( &voice.input_file, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, SOUND_RESAMPLE );
Sound_Process( &voice.input_file, voice.samplerate, voice.width, SOUND_RESAMPLE );
voice.input_file_pos = 0;
voice.start_time = Sys_DoubleTime();
@@ -418,7 +393,7 @@ void Voice_RecordStart( void )
}
}
if( !Voice_IsRecording( ) && voice.device_opened )
if( !Voice_IsRecording() )
voice.is_recording = VoiceCapture_Activate( true );
if( Voice_IsRecording() )
@@ -468,7 +443,7 @@ Feed the decoded data to engine sound subsystem
static void Voice_StartChannel( uint samples, byte *data, int entnum )
{
SND_ForceInitMouth( entnum );
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, bound( 0, 255 * voice_scale.value, 255 ));
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, 255 );
}
/*
@@ -480,11 +455,10 @@ Received encoded voice data, decode it
*/
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
{
const int playernum = ent - 1;
int samples = 0;
int ofs = 0;
if( playernum < 0 || playernum >= cl.maxclients || !voice.decoders[playernum] )
if( !voice.decoder )
return;
// decode frame by frame
@@ -504,7 +478,7 @@ void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
if( ofs + compressed_size > size )
break;
frame_samples = opus_custom_decode( voice.decoders[playernum], data + ofs, compressed_size,
frame_samples = opus_custom_decode( voice.decoder, data + ofs, compressed_size,
(opus_int16*)voice.decompress_buffer + samples, voice.frame_size );
ofs += compressed_size;
@@ -528,8 +502,8 @@ void CL_AddVoiceToDatagram( void )
if( cls.state != ca_active || !Voice_IsRecording() || !voice.encoder )
return;
size = Voice_GetOpusCompressedData( voice.compress_buffer, sizeof( voice.compress_buffer ), &frames );
size = Voice_GetOpusCompressedData( voice.output_buffer, sizeof( voice.output_buffer ), &frames );
if( size > 0 && MSG_GetNumBytesLeft( &cls.datagram ) >= size + 32 )
{
@@ -537,7 +511,7 @@ void CL_AddVoiceToDatagram( void )
MSG_WriteByte( &cls.datagram, voice_loopback.value != 0 );
MSG_WriteByte( &cls.datagram, frames );
MSG_WriteShort( &cls.datagram, size );
MSG_WriteBytes( &cls.datagram, voice.compress_buffer, size );
MSG_WriteBytes( &cls.datagram, voice.output_buffer, size );
}
}
@@ -553,7 +527,6 @@ void Voice_RegisterCvars( void )
Cvar_RegisterVariable( &voice_enable );
Cvar_RegisterVariable( &voice_loopback );
Cvar_RegisterVariable( &voice_scale );
Cvar_RegisterVariable( &voice_transmit_scale );
Cvar_RegisterVariable( &voice_avggain );
Cvar_RegisterVariable( &voice_maxgain );
Cvar_RegisterVariable( &voice_inputfromfile );
@@ -571,9 +544,8 @@ static void Voice_Shutdown( void )
int i;
Voice_RecordStop();
Voice_ShutdownOpusDecoder();
Voice_ShutdownOpusEncoder();
Voice_ShutdownCustomMode();
Voice_ShutdownOpusDecoder();
VoiceCapture_Shutdown();
if( voice.local.talking_ack )
@@ -599,17 +571,10 @@ void Voice_Idle( double frametime )
{
int i;
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ))
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ) && !voice_enable.value )
{
ClearBits( voice_enable.flags, FCVAR_CHANGED );
if( voice_enable.value )
{
if( cls.state == ca_active && COM_CheckString( voice_codec_init ) && voice_quality_init != 0 )
Voice_Init( voice_codec_init, voice_quality_init, false );
}
else
Voice_Shutdown();
Voice_Shutdown();
return;
}
// update local player status first
@@ -628,20 +593,6 @@ Initialize the voice subsystem
*/
qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
{
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
{
if( COM_CheckStringEmpty( pszCodecName ))
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
// reset saved codec name, we won't enable voice for this connection
voice_codec_init[0] = 0;
voice_quality_init = 0;
return false;
}
Q_strncpy( voice_codec_init, pszCodecName, sizeof( voice_codec_init ));
voice_quality_init = quality;
if( !voice_enable.value )
return false;
@@ -649,12 +600,20 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
if( Q_strcmp( pszCodecName, voice.codec ) || voice.quality != quality )
{
Voice_Shutdown();
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
{
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
return false;
}
voice.autogain.block_size = 128;
if( !Voice_InitCustomMode( ))
if( !Voice_InitOpusDecoder( ))
{
// no reason to init encoder and open audio device
// if we can't hear other players
Con_Printf( S_ERROR "Voice chat disabled.\n" );
Voice_Shutdown();
return false;
}
@@ -674,16 +633,6 @@ qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
if( !preinit )
{
Voice_ShutdownOpusDecoder();
if( !Voice_InitOpusDecoder())
{
// no reason to init encoder and open audio device
// if we can't hear other players
Con_Printf( S_ERROR "Can't create decoders, voice chat is disabled.\n" );
Voice_Shutdown();
return false;
}
voice.device_opened = VoiceCapture_Init();
if( !voice.device_opened )

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