Compare commits

..

6 Commits

356 changed files with 18579 additions and 23932 deletions

View File

@@ -1,27 +0,0 @@
image: alpine/latest
packages:
- build-base
- sdl2-dev
- freetype-dev
- fontconfig-dev
- opus-dev
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:
- client: |
cd xash3d-fwgs
./waf configure -8 --enable-tests --enable-engine-tests build install --destdir=bin
- server: |
cd xash3d-fwgs
./waf configure --reconfigure --dedicated build install --destdir=bin
- run-tests: |
cd xash3d-fwgs/bin
export SDL_VIDEODRIVER=wayland
./xash3d -runtests
./xash -runtests
rm -rf valve/gameinfo.txt test_*
- package: |
cd xash3d-fwgs/bin
tar -cjvf xash3d-fwgs-alpine-amd64.tar.bz2 *
artifacts:
- xash3d-fwgs/bin/xash3d-fwgs-alpine-amd64.tar.bz2

View File

@@ -1,30 +0,0 @@
image: debian/sid
arch: amd64
packages:
- build-essential
- python-is-python3
- libsdl2-dev
- libfreetype-dev
- libfontconfig-dev
- libopus-dev
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:
- client: |
cd xash3d-fwgs
./waf configure -8 --enable-tests --enable-engine-tests build install --destdir=bin
- server: |
cd xash3d-fwgs
./waf configure --reconfigure --dedicated build install --destdir=bin
- run-tests: |
cd xash3d-fwgs/bin
export SDL_VIDEODRIVER=wayland
./xash3d -runtests
./xash -runtests
rm -rf valve/gameinfo.txt test_*
- package: |
cd xash3d-fwgs/bin
tar -cjvf xash3d-fwgs-debian-arm64.tar.bz2 *
artifacts:
- xash3d-fwgs/bin/xash3d-fwgs-debian-arm64.tar.bz2

View File

@@ -1,29 +0,0 @@
image: debian/sid
packages:
- build-essential
- python-is-python3
- libsdl2-dev
- libfreetype-dev
- libfontconfig-dev
- libopus-dev
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:
- client: |
cd xash3d-fwgs
./waf configure -8 --enable-tests --enable-engine-tests build install --destdir=bin
- server: |
cd xash3d-fwgs
./waf configure --reconfigure --dedicated build install --destdir=bin
- run-tests: |
cd xash3d-fwgs/bin
export SDL_VIDEODRIVER=wayland
./xash3d -runtests
./xash -runtests
rm -rf valve/gameinfo.txt test_*
- package: |
cd xash3d-fwgs/bin
tar -cjvf xash3d-fwgs-debian-amd64.tar.bz2 *
artifacts:
- xash3d-fwgs/bin/xash3d-fwgs-debian-amd64.tar.bz2

View File

@@ -1,29 +0,0 @@
image: freebsd/latest
packages:
- lang/python
- devel/pkgconf
- devel/sdl20
- print/freetype2
- x11-fonts/fontconfig
- audio/opus
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:
- client: |
cd xash3d-fwgs
./waf configure --enable-tests --enable-engine-tests build install --destdir=bin
- server: |
cd xash3d-fwgs
./waf configure --reconfigure --dedicated build install --destdir=bin
- run-tests: |
cd xash3d-fwgs/bin
export SDL_VIDEODRIVER=wayland
./xash3d -runtests
./xash -runtests
rm -rf valve/gameinfo.txt test_*
- package: |
cd xash3d-fwgs/bin
tar -cjvf xash3d-fwgs-freebsd-amd64.tar.bz2 *
artifacts:
- xash3d-fwgs/bin/xash3d-fwgs-freebsd-amd64.tar.bz2

View File

@@ -1,29 +0,0 @@
image: netbsd/latest
packages:
- python311
- SDL2
- freetype2
- fontconfig
- libopus
- pkgconf
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:
- client: |
cd xash3d-fwgs
python3.11 waf configure --enable-tests --enable-engine-tests build install --destdir=bin
- server: |
cd xash3d-fwgs
python3.11 waf configure --reconfigure --dedicated build install --destdir=bin
- run-tests: |
cd xash3d-fwgs/bin
export SDL_VIDEODRIVER=wayland
./xash3d -runtests
./xash -runtests
rm -rf valve/gameinfo.txt test_*
- package: |
cd xash3d-fwgs/bin
tar -cjvf xash3d-fwgs-netbsd-amd64.tar.bz2 *
artifacts:
- xash3d-fwgs/bin/xash3d-fwgs-netbsd-amd64.tar.bz2

View File

@@ -1,26 +0,0 @@
image: openbsd/latest
packages:
- python3
- sdl2
- opus
sources:
- https://git.sr.ht/~a1batross/xash3d-fwgs
tasks:
- client: |
cd xash3d-fwgs
python3 waf configure --enable-tests --enable-engine-tests build install --destdir=bin
- server: |
cd xash3d-fwgs
python3 waf configure --reconfigure --dedicated build install --destdir=bin
- run-tests: |
cd xash3d-fwgs/bin
export SDL_VIDEODRIVER=wayland
./xash3d -runtests
./xash -runtests
rm -rf valve/gameinfo.txt test_*
- package: |
cd xash3d-fwgs/bin
tar -cjvf xash3d-fwgs-openbsd-amd64.tar.bz2 *
artifacts:
- xash3d-fwgs/bin/xash3d-fwgs-openbsd-amd64.tar.bz2

View File

@@ -1,22 +1,34 @@
task:
name: freebsd-14-amd64
name: freebsd-12-amd64
freebsd_instance:
image_family: freebsd-14-0
image_family: freebsd-12-3
setup_script:
- pkg update
- pkg install -y pkgconf git sdl2 python fontconfig opus
- pkg install -y git sdl2 python fontconfig
- git submodule update --init --recursive
test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated
- ./scripts/cirrus/build_freebsd.sh full
task:
name: freebsd-15-amd64
name: freebsd-13-amd64
freebsd_instance:
image_family: freebsd-15-0-snap
image_family: freebsd-13-1
setup_script:
- pkg update
- pkg install -y pkgconf git sdl2 python fontconfig opus
- pkg install -y git sdl2 python fontconfig
- 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-snap
setup_script:
- pkg update
- pkg install -y git sdl2 python fontconfig
- git submodule update --init --recursive
test_script:
- ./scripts/cirrus/build_freebsd.sh dedicated

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

@@ -13,8 +13,6 @@ jobs:
fail-fast: false
matrix:
include:
# Linux build specifically want oldest Ubuntu as possible
# to be crossdistribution compatible, otherwise use ubuntu-latest
- os: ubuntu-20.04
targetos: linux
targetarch: amd64
@@ -24,28 +22,34 @@ jobs:
# - os: ubuntu-aarch64-20.04
# targetos: linux
# targetarch: aarch64
- os: ubuntu-20.04
targetos: android
targetarch: multiarch
# - os: ubuntu-20.04
# targetos: android
# targetarch: 32
# - os: ubuntu-20.04
# targetos: android
# targetarch: 64
# - os: ubuntu-20.04
# targetos: motomagx
# targetarch: armv6
- os: ubuntu-latest
- os: ubuntu-20.04
targetos: nswitch
targetarch: arm64
- os: ubuntu-latest
- os: ubuntu-20.04
targetos: psvita
targetarch: armv7hf
- os: windows-latest
targetos: win32
targetarch: amd64
- os: windows-2019 # always use the oldest possible for 32-bit because of older compilers, and better support of certain legacy OSes
- os: windows-latest
targetos: win32
targetarch: i386
env:
SDL_VERSION: 2.30.3
SDL_VERSION: 2.26.2
GH_CPU_ARCH: ${{ matrix.targetarch }}
ANDROID_SDK_TOOLS_VER: 4333796
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -76,7 +80,7 @@ jobs:
with:
submodules: recursive
- name: Build flatpak (Compat.i386)
uses: FWGS/flatpak-github-actions/flatpak-builder@v6.1
uses: FWGS/flatpak-github-actions/flatpak-builder@v5
with:
bundle: ${{ matrix.app }}.flatpak
manifest-path: scripts/flatpak/${{ matrix.app }}.yml

9
.gitignore vendored
View File

@@ -54,18 +54,12 @@ CMakeFiles
Makefile
cmake_install.cmake
install_manifest.txt
CMakeLists.txt*
CMakeScripts
Testing
compile_commands.json
_deps
# makedepend
Makefile.dep
*.bak
ALL_BUILD.*
INSTALL.*
ZERO_CHECK.*
CMakeLists.txt
# Visual Studio
*.obj
@@ -339,6 +333,3 @@ __pycache__
.history/*
.cache/*
enc_temp_folder/
# KDevelop4
*.kdev4

View File

@@ -18,7 +18,7 @@ def build(bld):
target = 'gl4es',
features = 'c',
includes = ['gl4es/src', 'gl4es/src/gl', 'gl4es/src/glx', 'gl4es/include'],
defines = ['NOX11', 'NO_GBM', 'NO_INIT_CONSTRUCTOR', 'DEFAULT_ES=2', 'NOEGL', 'NO_LOADER', 'STATICLIB'],
defines = ['NOX11', 'NO_GBM', 'NO_INIT_CONSTRUCTOR', 'DEFAULT_ES=2', 'NOEGL', 'EXTERNAL_GETPROCADDRESS=GL4ES_GetProcAddress', 'NO_LOADER', 'STATICLIB'],
cflags = ['-w', '-fvisibility=hidden', '-std=gnu99'],
subsystem = bld.env.MSVC_SUBSYSTEM,
export_includes = '.')

View File

@@ -1,16 +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 |
### 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,24 +0,0 @@
# Developers donation page
On this page you can find links where you can support each developer individually, who has provided public sponsorship information.
### [a1batross](https://github.com/a1batross)
* Initial Xash3D SDL2/Linux port author, Xash3D FWGS engine maintainer, creator of non-commercial Flying With Gauss organization.
* Boosty page: https://boosty.to/a1ba
### [nekonomicon](https://github.com/nekonomicon)
* [hlsdk-portable](https://github.com/FWGS/hlsdk-portable), [mdldec](../utils/mdldec), [opensource-mods.md](opensource-mods.md) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=nekonomicon) (*BSD/clang port, PNG support, etc).
* Boosty page: https://boosty.to/nekonomicon
### [Velaron](https://github.com/Velaron)
* [cs16-client](https://github.com/Velaron/cs16-client) & [tf15-client](https://github.com/Velaron/tf15-client) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=Velaron) (Android port, voice chat, etc).
* BuyMeACoffee page: https://www.buymeacoffee.com/velaron
### [SNMetamorph](https://github.com/SNMetamorph)
* [PrimeXT](https://github.com/SNMetamorph/PrimeXT) & [GoldSrc Monitor](https://github.com/SNMetamorph/goldsrc-monitor) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=SNMetamorph) (Windows port, voice chat, etc).
* BTC: `16GAzK3qei5AwBW7sggXp3yNcFHBtdpxXj`
* ETH (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
* USDT (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
* USDC (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`

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

@@ -1,25 +0,0 @@
# GetNativeObject API
To be able to use platform-specific features or get optional engine interfaces, we've added a simple call to MobilityAPI on client DLL and PhysicsAPI for server DLL and extended MenuAPI for menu DLL.
It's defined like this:
```
void *pfnGetNativeObject( const char *name );
```
#### Cross-platform objects
Only these objects are guaranteed to be available on all targets.
| Object name | Interface |
|-------------|-----------|
| `VFileSystem009` | Provides C++ interface to filesystem, binary-compatible with Valve's VFileSystem009. |
| `XashFileSystemXXX` | Provides C interface to filesystem. This interface is unstable and not recommended for generic use, outside of engine internals. For more info about current version look into `filesystem.h`. |
#### Android-specific objects
| Object name | Interface |
|-------------|-----------|
| `JNIEnv` | Allows interfacing with Java Native Interface. |
| `ActivityClass` | Returns JNI object for engine Android activity class. |

View File

@@ -1,65 +0,0 @@
# sounds.lst.md
Using sounds.lst located in scripts folder, modder can override some of the hardcoded sounds in temp entities and server physics.
File format:
```
<group name>
{
<path1>
<path2>
<path3>
}
<group2 name> <path with %d> <min number> <max number>
```
* Sounds can use any supported sound format (WAV or MP3).
* The path must be relative to the sounds/ folder in the game or base directory root, addon folder, or archive root.
* Groups can be empty or omitted from the file to load no sound.
* Groups can either list a set of files or specify a format string and a range.
* Anything after // will be considered a comment and ignored.
* Behavior is undefined if the group was listed multiple times.
Currently supported groups are:
|Group name|Usage|
|----------|-----|
|`BouncePlayerShell`|Used for BOUNCE_SHELL tempentity hitsound|
|`BounceWeaponShell`|Used for BOUCNE_SHOTSHELL tempentity hitsound|
|`BounceConcrete`|Used for BOUNCE_CONCRETE tempentity hitsound|
|`BounceGlass`|Used for BOUCNE_GLASS|
|`BounceMetal`|Used for BOUNCE_METAL|
|`BounceFlesh`|Used for BOUNCE_FLESH|
|`BounceWood`|Used for BOUNCE_WOOD|
|`Ricochet`|Used for BOUNCE_SHRAP and ricochet tempentities|
|`Explode`|Used for tempentity explosions|
|`EntityWaterEnter`|Used for entity entering water|
|`EntityWaterExit`|Used for entity exiting water|
|`PlayerWaterEnter`|Used for player entering water|
|`PlayerWaterExit`|Used for player exiting water|
## Example
This example is based on defaults sounds used in Half-Life:
```
BouncePlayerShell "player/pl_shell%d.wav" 1 3
BounceWeaponShell "weapons/sshell%d.wav" 1 3
BounceConcrete "debris/concrete%d.wav" 1 3
BounceGlass "debris/glass%d.wav" 1 4
BounceMetal "debris/metal%d.wav" 1 6
BounceFlesh "debris/flesh%d.wav" 1 7
BounceWood "debris/wood%d.wav" 1 4
Ricochet "weapons/ric%d.wav" 1 5
Explode "weapons/explode%d.wav" 3 5
EntityWaterEnter "player/pl_wade%d.wav" 1 4
EntityWaterExit "player/pl_wade%d.wav" 1 4
PlayerWaterEnter
{
"player/pl_wade1.wav"
}
PlayerWaterExit
{
"player/pl_wade2.wav"
}
```

View File

@@ -1,116 +0,0 @@
# Game definition and information file
gameinfo.txt is an essential part of any Xash3D based game. It allows basic customization for games creators, like setting game title, DLL paths, etc.
This document defines gameinfo.txt syntax, supported keys and liblist.gam conversion rules for the latest version of the engine. Note for engine developers, keep this document in sync with an implementation.
## gameinfo.txt syntax
* gameinfo.txt is a simple list of keys and values, separated by newline.
* You can add single line comments using double slashes (//).
* Keys can accept integer, float, string or boolean values.
* Boolean keys use 0 as false and 1 as true value.
* To have spaces in string values, you must enclose them in double quotes. Then, to have double quotes, you must escape it with backslash, and to have a backslash you need to use double backslashes.
The example:
```
// this is a comment :)
// this is another comment
some_integer_key 123
this_is_float_key 13.37 // optional comment
enable_feature 1 // boolean, 1 to enable, 0 to disable
example_string_key string_value
example_spaces "string with spaces"
example_title "Fate\\Stay Night" // engine will parse it as Fate\Stay Night
```
## gameinfo.txt keys
This is a list of all gameinfo.txt keys supported by the engine. Be aware that the engine will silently skip all unrecognized keys.
| Key | Type | Default value | Description |
| ---------------- | ---------- | --------------- | ----------- |
| `ambient0` | string | Empty string | Automatic ambient sound |
| `ambient1` | string | Empty string | Automatic ambient sound |
| `ambient2` | string | Empty string | Automatic ambient sound |
| `ambient3` | string | Empty string | Automatic ambient sound |
| `basedir` | string | `valve` | Game base directory, used to share assets between games |
| `date` | string | Empty string | Game release date. Unused. |
| `dllpath` | string | `cl_dlls` | Game DLL path. Engine will search custom DLLs (client or menu, for example) in this directory, except `gamedll`, see below. |
| `fallback_dir` | string | Empty string | Additional game base directory |
| `gamedir` | string | Current gamedir | Game directory, ignored in FWGS, as game directory is defined by the game directory name |
| `gamedll` | string | `dlls/hl.dll` | Game server DLL for 32-bit x86 Windows (see LibraryNaming.md for details) |
| `gamemode` | string | Empty string | Game type. When set to `singleplayer_only` or `multiplayer_only` marks the game as SP or MP only respectively, hiding the option in game UI. Omitting this key or using custom values mark the game as both MP and SP compatible. |
| `icon` | string | `game.ico` | Game icon. Engine will automatically append .ico and may automatically switch to .tga icon as well |
| `max_beams` | integer | 128 | Beams limit, 64 min, 512 max |
| `max_edicts` | integer | 900 | Entities limit, 600 min, 8192 max (protocol limit). In FWGS, minimum is 64. |
| `max_particles` | integer | 4096 | Particles limit, 1024 min, 131072 max |
| `max_tempents` | integer | 500 | Temporary entities limit. 300 min, 2048 max |
| `mp_entity` | string | `info_player_deathmatch` | Entity used to mark maps as multiplayer |
| `mp_filter` | string | Empty string | When set, used to filter multiplayer maps instead of `mp_entity`.<br>If the map name starts with the same characters as this filter, it's considered a multiplayer map |
| `nomodels` | boolean | 0 | When set to 1, disallows changing player model in UI |
| `noskills` | boolean | 0 | When set to 1, disallows selection of game difficulty |
| `secure` | boolean | 0 | When set to 1, original Unkle Mike's engine will completely disable developer mode. FWGS ignores but preserves this value for compatibility. |
| `size` | integer | 0 | Game directory size in bytes, used in Change Game dialog only |
| `startmap` | string | `c0a0` | The name of the map used in new game |
| `sp_entity` | string | `info_player_start` | Entity used to mark map as single player. Used in map validation |
| `title` | string | `New Game` | Game title, used in window title, default server name, etc. |
| `trainmap` | string | `t0a0` | The name of the training map (Hazard Course) |
| `type` | string | Empty string | Game type, used in Change Game UI. |
| `url_info` | string | Empty string | Game homepage URL, used in Change Game UI |
| `url_update` | string | Empty string | Game updates URL, used in Settings UI |
| `version` | float | 1.0 | Game version, used in Change Game dialog and in server info |
## FWGS-specific gameinfo.txt keys
These strings are specific to Xash3D FWGS.
| Key | Type | Default value | Description |
| ----------------------- | ---------- | ------------------------ | ----------- |
| `animated_title` | boolean | 0 | Use animated title in main menu (WON Half-Life logo.avi imitation from Half-Life 25-th anniversary update)
| `autosave_aged_count` | integer | 2 | Auto saves limit used in saves rotation |
| `gamedll_linux` | string | Generated from `gamedll` | Game server DLL for 32-bit x86 Linux (see LibraryNaming.md for details) |
| `gamedll_osx` | string | Generated from `gamedll` | Game server DLL for 32-bit x86 macOS (see LibraryNaming.md for details) |
| `hd_background` | boolean | 0 | Use HD background for main menu (Half-Life 25-th anniversary update) |
| `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 |
## Note on GoldSrc liblist.gam support
As Xash3D accidentally supports GoldSrc games, it also supports parsing liblist.gam.\
Xash3D will use this file if gameinfo.txt is absent, or if its modification timestamp is older than liblist.gam.
For game creators who plan supporting only Xash3D, using this file is not recommended.
The table below defines conversion rules from liblist.gam to gameinfo.txt. Some keys' interpretation does differ from `gameinfo.txt`, in this case a note will be left. If `liblist.gam` key isn't present in this table, it's ignored.
| `liblist.gam` key | `gameinfo.txt` key | Note |
| ----------------- | ------------------ | ---- |
| `animated_title` | `animated_title` | |
| `edicts` | `max_edicts` | |
| `fallback_dir` | `fallback_dir` | |
| `game` | `title` | |
| `gamedir` | `gamedir` | |
| `gamedll` | `gamedll` | |
| `gamedll_linux` | `gamedll_linux` | |
| `gamedll_osx` | `gamedll_osx` | |
| `hd_background` | `hd_background` | |
| `icon` | `icon` | |
| `mpentity` | `mp_entity` | |
| `mpfilter` | `mp_filter` | |
| `nomodels` | `nomodels` | |
| `secure` | `secure` | In GoldSrc it's used to mark the multiplayer game as anti-cheat enabled.<br>Original Xash3D misinterprets its value for disallowing console and developer mode.<br>FWGS ignores this key but preserves for compatibility. |
| `startmap` | `startmap` | |
| `size` | `size` | |
| `trainingmap` | `trainmap` | |
| `trainmap` | `trainmap` | |
| `type` | `type` & `gamemode`| In `liblist.gam` this key works as both `type` and `gamemode`.<br>If value is `singleplayer_only` or `multiplayer_only` the game is marked as SP or MP only, and `gameinfo.txt` type set to `Single` or `Multiplayer`.<br>Any custom value will mark the game as both SP and MP compatible, and type is set to whatever custom value. |
| `url_dl` | `url_update` | |
| `url_info` | `url_info` | |
| `version` | `version` | |

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

@@ -1,15 +0,0 @@
# Xash3D FWGS on `musl`
Xash3D FWGS works on `musl` out of the box. However, the engine doesn't try to differentiate glibc and musl anymore. If you see error similar to:
```
Host_InitError: can't initialize cl_dlls/client.so: Error relocating valve/cl_dlls/client.so: __sprintf_chk: symbol not found
```
... or you know that the game you're running is linked against glibc, you can try using `libgcompat`, like this:
```
$ LD_PRELOAD=/lib/libgcompat.so.0 ./xash3d ...
```
It will automatically add the missing symbols that glibc binaries usually need. In the future we might automatically link engine against `libgcompat` for better compatibility with prebuilt or closed-source games, if there will be any use for this.

View File

@@ -17,7 +17,7 @@ Mirrored on github - https://github.com/JoelTroch/am_src_rebirth
Mirrored on github - https://github.com/nekonomicon/BattleGrounds
## Bubblemod
Download page on official site(WM snapshot) - [http://www.bubblemod.org/dl_default.php](https://web.archive.org/web/20130717133158/http://www.bubblemod.org/dl_default.php)
Download page on official site - http://www.bubblemod.org/dl_default.php (dead link!)
Mirrored on github - https://github.com/HLSources/BubbleMod
@@ -85,9 +85,6 @@ Official gitlab repository - https://gitlab.com/Sockman/hltopdown
## Half-Life: Update
Official github repository - https://github.com/Fograin/hl-subsmod-ex
## Half-Life: Rally
Official gitlab repository - https://gitlab.com/hlrally/src
## Half-Life: Weapon Edition
Available on ModDB - https://www.moddb.com/mods/half-life-weapon-edition/downloads/half-life-weapon-edition-1508-alpha-open-src
@@ -133,8 +130,22 @@ Available in mod archive on ModDB - https://www.moddb.com/mods/overturn
## Oz Deathmatch
Mirrored on github - https://github.com/nekonomicon/OZDM
## Spirit of Half-Life
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
## Threewave CTF
*Unfinished mod by Valve Software*
Available in Valve's Half-Life repository with Deathmatch Classic sources - https://github.com/ValveSoftware/halflife/tree/master/dmc
## Trinity Render
Available on ModDB: https://www.moddb.com/mods/half-life-episode-two/downloads/trinity-rendering-engine-v308f
## Tyrian: Ground Assault
Available on ModDB: https://www.moddb.com/mods/tyriangroundassault/downloads/tyrianga-v1-0-src
## Paranoia
Available on ModDB - https://www.moddb.com/mods/paranoia/downloads/paranoia-toolkit
Available on ModDB: https://www.moddb.com/mods/paranoia/downloads/paranoia-toolkit
## Paranoia 2: The Savior
Prealpha, mirrored on github - https://github.com/a1batross/Paranoia2_ancient
@@ -149,37 +160,12 @@ Was found on HLFX - http://hlfx.ru/forum/showthread.php?s=2c892dfc52f72be52a89c3
## Ricochet
Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/ricochet
## Spirit of Half-Life
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
## The Wastes
Version 1.5: mirrored on code.idtech.space - https://code.idtech.space/vera/halflife-thewastes-sdk
## Threewave CTF
*Unfinished mod by Valve Software*
Available in Valve's Half-Life repository with Deathmatch Classic sources - https://github.com/ValveSoftware/halflife/tree/master/dmc
## Trinity Render
Available on ModDB - https://www.moddb.com/mods/half-life-episode-two/downloads/trinity-rendering-engine-v308f
## Tyrian: Ground Assault
Available on ModDB - https://www.moddb.com/mods/tyriangroundassault/downloads/tyrianga-v1-0-src
## Wasteland
Mirrored on code.idtech.space - https://code.idtech.space/vera/halflife-wasteland-sdk
## Wizard Wars
Download page on official site - http://www.thothie.com/ww/
## XashXT
Mirrored on github - https://github.com/a1batross/XashXT_original
## Xen-Warrior
*Source code is a part of Spirit of Half-Life 1.0-1.2 under XENWARRIOR macro*
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
## Zombie-X
Available in mod archive on ModDB - https://www.moddb.com/mods/zombie-x-10-final/downloads/zombie-x-10-dle-beta6-last-version
@@ -201,12 +187,12 @@ malortie's recreation - https://github.com/malortie/hl-aom
Branch **aom** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aom
## Afraid of Monsters: Director's cut
Reverse-engineered code: branch **aomdc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aomdc
Reverse-engineered code, branch **aomdc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aomdc
## Azure Sheep
malortie's recreation - https://github.com/malortie/hl-asheep
Reverse-engineered code: branch **asheep** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/asheep
Reverse-engineered code, branch **asheep** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/asheep
## Big Lolly
malortie's recreation - https://github.com/malortie/hl-biglolly
@@ -228,7 +214,7 @@ Branch **caseclosed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable
Branch **CAd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/CAd
## Counter Strike
Reverse-engineered code of client part by a1batross - https://github.com/Velaron/cs16-client
Reverse-engineered code of client part by a1batross - https://github.com/FWGS/cs16-client/tree/v1.32
Reverse-engineered code of server part by nagist - https://github.com/nagist/cs16nd
@@ -240,22 +226,15 @@ CSO-like Xash3D-based mod, CSMoE - https://github.com/MoeMod/CSMoE
## Crack-Life: Campaign Mode
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/crack_life
Reverse-engineered code: branch **clcampaign** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/clcampaign
## Escape from the Darkness
malortie's recreation - https://github.com/malortie/hl-eftd
Reverse-engineered code: branch **eftd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/eftd
## Half-Life: Black Guard
*This mod uses dlls from Cleaner's Adventures*
Branch **CAd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/CAd
Reverse-engineered code, branch **eftd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/eftd
## Half-Life: Blue Shift
Unkle Mike's recreation - https://hlfx.ru/forum/showthread.php?s=&threadid=5253
Reverse-engineered code: branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift
Reverse-engineered code, branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift
## Half-Life: Induction
Branch **induction** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/induction
@@ -263,12 +242,12 @@ Branch **induction** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/
## Half-Life: Opposing Force
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/hlsdk-xash3d
Reverse-engineered code: clean branch **opfor** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/opfor
Reverse-engineered code, clean branch **opfor** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/opfor
Spirit of Half Life: Opposing-Force Edition - https://github.com/Hammermaps-DEV/SOHL-V1.9-Opposing-Force-Edition
## Half-Life: Rebellion
Reverse-engineered code: branch **rebellion** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/rebellion
Reverse-engineered code, branch **rebellion** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/rebellion
## Half-Life: Urbicide
Branch **hl_urbicide** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/hl_urbicide
@@ -276,7 +255,7 @@ Branch **hl_urbicide** in hlsdk-portable - https://github.com/FWGS/hlsdk-portabl
## Half-Life: Visitors
malortie's recreation - https://github.com/malortie/hl-visitors
Reverse-engineered code: branch **visitors** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/visitors
Reverse-engineered code, branch **visitors** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/visitors
## Half-Secret
Branch **half-secret** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/half-secret
@@ -289,18 +268,18 @@ Branch **noffice** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tr
## Poke 646
malortie's recreation - https://github.com/malortie/hl-poke646
Reverse-engineered code: branch **poke646** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646
Reverse-engineered code, branch **poke646** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646
## Poke 646: Vendetta
malortie's recreation - https://github.com/malortie/hl-poke646-vendetta
Reverse-engineered code: branch **poke646_vendetta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646_vendetta
Reverse-engineered code, branch **poke646_vendetta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646_vendetta
## Residual Life
Reverse-engineered code: branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
Reverse-engineered code, branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
## Residual Point
Reverse-engineered code: branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
Reverse-engineered code, branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
## Sewer Beta
Branch **sewer_beta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sewer_beta
@@ -311,12 +290,12 @@ Reverse-engineered code by Velaron - https://github.com/Velaron/tf15-client
## The Gate
malortie's recreation - https://github.com/malortie/hl-thegate
Reverse-engineered code: branch **thegate** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/thegate
Reverse-engineered code, branch **thegate** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/thegate
## They Hunger
malortie's recreation - https://github.com/malortie/hl-theyhunger
Reverse-engineered code: branch **theyhunger** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/theyhunger
Reverse-engineered code, branch **theyhunger** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/theyhunger
They Hunger: Tactical - https://www.moddb.com/mods/they-hunger-tactical/downloads/tht-source-code-documentation
@@ -359,22 +338,16 @@ Branch **half-screwed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portab
Port to Linux - https://github.com/fmoraw/NS
## Spirit of Half-Life
Version 1.2: branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
Version 1.2, branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
## Swiss Cheese Halloween 2002
Just more playable version by malortie - https://github.com/malortie/hl-shall
Branch **halloween** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/halloween
## The Wastes
Version 1.5: Port to Linux - https://git.mentality.rip/a1batross/halflife-thewastes-sdk
## Threewave CTF
Branch **dmc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/dmc
## Xen-Warrior
Branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
## Zombie-X
Branch **zombie-x** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/zombie-x

View File

@@ -2,32 +2,38 @@ Xash3D FWGS is intended to be easily ported to specific platform, however main i
This page is about merged ports to main source tree and responsible for it developers.
For porting guidelines, look engine-porting-guide.md.
For porting guidelines, look here(TODO!)
Status:
* **Supported**: active, was confirmed to be fully functional.
* **Supported**: active, confirmed to be fully functional.
* **In progress**: active, under development.
* **Incomplete**: not active, but some work was accepted to main repository before
* **Old Engine**: port was for old engine fork
* **Not maintained**: lack of human resources
* **Not merged**: was done in third-party fork, real status unknown
* **Deprecated**: not supported anymore
Table is sorted by status and platform.
Table is sorted by status.
| Platform | Status | Maintainer | Note
| -------- | ------ | ---------- | ----
| Android | Supported | @Velaron |
| Windows | Supported | @a1batross, @SNMetamorph |
| *BSD | Supported | @nekonomicon |
| DOS4GW | Supported | @mittorn |
| GNU/Linux | Supported | @a1batross, @mittorn |
| Haiku | Supported | not maintained | Was added by #478 and #483
| macOS | Supported | @sofakng |
| GNU/Linux(x86, amd64, arm) | Supported | @a1batross, @mittorn |
| Android | Supported | @a1batross, @mittorn |
| MotoMAGX | Supported | @a1batross |
| GNU/Linux(elbrus) | Supported | @a1batross, @mittorn | Rare and eventual access to e2k machine
| Haiku | Supported | not maintained | Was added by #478 and #483
| DOS4GW | Supported | @mittorn |
| GNU/Linux(mipsel) | Supported | @mittorn |
| PSVita | Supported | @fgsfdsfgs |
| Switch | Supported | @fgsfdsfgs |
| Windows | Supported | @a1batross, @SNMetamorph |
| Wii | In progress | Collaborative effort | [GitHub Repository](https://github.com/saucesaft/xash3d-wii)
| PSP | In progress | @Crow_bar, @Velaron | [GitHub Repository](https://github.com/Crow-bar/xash3d-fwgs)
| Wii | In progress | Collaborative effort | [GitHub Repository](https://github.com/saucesaft/xash3d-wii)
| Emscripten | Old Engine | not maintained |
| 3DS | Old Engine fork | not maintained | [GitHub Repository](https://github.com/masterfeizz/Xash3DS)
| Oculus Quest | Old Engine fork | @DrBeef | [GitHub Repository](https://github.com/DrBeef/Lambda1VR)
| PSVita | Old Engine fork | not maintained | [GitHub Repository](https://github.com/fgsfdsfgs/vitaXash3D)
| Switch | Old Engine fork | not maintained | [GitHub Repository](https://github.com/switchports/xash3d-switch)
| 3DS | Old Engine fork | not maintained | [GitHub Repository](https://github.com/masterfeizz/Xash3DS)
| macOS | Deprecated | not maintained | See GitHub issue #61
| iOS | Deprecated | not maintained | See GitHub issue #61

View File

@@ -0,0 +1,41 @@
# Experimental VGUI2 Support
Thanks to @kungfulon contributions, Xash3D FWGS now supports VGUI2.
VGUI2 is undocumented UI system from Source Engine that GoldSrc used in some games and it's main menu.
## Support status
Doesn't draw anything, doesn't take any input.
## List of games that require VGUI2 support
- Counter-Strike 1.6
- Counter-Strike: Condition Zero
- Counter-Strike: Condition Zero Deleted Scenes
- Day of Defeat
- Half-Life: Blue Shift
## How to enable VGUI2 support
By default, engine doesn't initialize VGUI2 to not confuse existing games and mods that use or do not use VGUI1. This support also relies on a number of proprietary libraries, that we better not redistribute, so you have to supply them yourself. Keep in mind, that these libraries are compiled only for 32-bit Windows, Linux and OSX, you shouldn't expect them running anywhere else.
1. Download latest Half-Life from Steam.
2. Open local files.
3. Copy libraries in the list below according to your platform, to folder where Xash3D searches it's libraries (usually in same folder where executable is located)
| Linux | Windows
| -------- | --------
| `chromehtml.so` | `chromehtml.dll`
| `vgui2.so` | `vgui2.dll`
| `libcef.so` | `libcef.dll`
| `libtier0.so` | `tier0.dll`
| `libvstdlib.so` | `vstdlib.dll`
| `libsteam_api.so` | `steam_api.dll`
Some files must also be copied:
- `cef_gtk.pak`
Additionally, on Linux other libraries must be provided. Use `ldd` tool to figure out which libraries you miss. Many of them can be pulled from Steam Runtime.
Do not recommend using RoDir with VGUI2 games. Many of them are broken. Steam API will crash without `steam_appid.txt` in Xash root directory.

View File

@@ -1,27 +1,33 @@
# Xash3D FWGS Engine <img align="right" width="128" height="128" src="https://github.com/FWGS/xash3d-fwgs/raw/master/game_launch/icon-xash-material.png" alt="Xash3D FWGS icon" />
[![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 FWGS Engine
[![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 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 fork of Xash3D Engine by Unkle Mike with extended features and crossplatform.
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
## Donate
[![Donate to FWGS button](https://img.shields.io/badge/Donate_to_FWGS-%3C3-magenta)](Documentation/donate.md) \
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).
```
Xash3D is a game engine, aimed to provide compatibility with Half-Life Engine,
as well as to give game developers well known workflow and extend it.
Read more about Xash3D on ModDB: https://www.moddb.com/engines/xash3d-engine
```
## Fork features
* 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 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)
* Different input methods: touch and gamepad in addition to mouse & keyboard.
* HLSDK 2.4 support.
* Crossplatform: supported x86 and ARM on Windows/Linux/BSD/Android. ([see docs for more info](Documentation/ports.md))
* Modern compilers support: say no more to MSVC6.
* Better multiplayer support: multiple master servers, headless dedicated server.
* Mobility API: allows better game integration on mobile devices(vibration, touch controls)
* Different input methods: touch, gamepad and classic mouse & keyboard.
* TrueType font rendering, as a part of mainui_cpp.
* External VGUI support module.
* PNG & KTX2 image format support.
* [A set of small improvements](Documentation/), without broken compatibility.
* Multiple renderers support: OpenGL, GLESv1, GLESv2, Software.
* Voice support.
* External filesystem module like in GoldSrc engine.
* External vgui support module.
* PNG image format support.
* A set of small improvements, without broken compatibility.
## Planned fork features
* Virtual Reality support and game API.
* Vulkan renderer.
## Installation & Running
0) Get Xash3D FWGS binaries: you can use [testing](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous) build or you can compile engine from source code.

View File

@@ -18,17 +18,21 @@ GNU General Public License for more details.
// video backends (XASH_VIDEO)
#define VIDEO_NULL 0
#define VIDEO_SDL 1
#define VIDEO_ANDROID 2
#define VIDEO_FBDEV 3
#define VIDEO_DOS 4
// audio backends (XASH_SOUND)
#define SOUND_NULL 0
#define SOUND_SDL 1
#define SOUND_OPENSLES 2
#define SOUND_ALSA 3
// input (XASH_INPUT)
#define INPUT_NULL 0
#define INPUT_SDL 1
#define INPUT_ANDROID 2
#define INPUT_EVDEV 3
// timer (XASH_TIMER)
@@ -41,13 +45,16 @@ GNU General Public License for more details.
// messageboxes (XASH_MESSAGEBOX)
#define MSGBOX_STDERR 0
#define MSGBOX_SDL 1
#define MSGBOX_ANDROID 2
#define MSGBOX_WIN32 3
#define MSGBOX_NSWITCH 4
// library loading (XASH_LIB)
#define LIB_NULL 0
#define LIB_POSIX 1
#define LIB_WIN32 2
#define LIB_STATIC 3
#endif /* BACKENDS_H */

View File

@@ -1,6 +1,6 @@
/*
vgl_shim.h - vitaGL custom immediate mode shim
Copyright (C) 2023 fgsfds
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
@@ -13,12 +13,13 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#pragma once
#ifndef BONEINFO_H
#define BONEINFO_H
// max verts in a single frame
#define GL2_MAX_VERTS 32768
typedef struct
{
vec3_t angles;
vec3_t origin;
} boneinfo_t;
int GL2_ShimInit( void );
void GL2_ShimInstall( void );
void GL2_ShimShutdown( void );
void GL2_ShimEndFrame( void );
#endif//BONEINFO_H

View File

@@ -9,20 +9,7 @@ NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 ==
========================================================================
*/
#define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24 || type == PF_LUMINANCE)
#define ImageCompressed( type ) \
( type == PF_DXT1 \
|| type == PF_DXT3 \
|| type == PF_DXT5 \
|| type == PF_ATI2 \
|| type == PF_BC4_SIGNED \
|| type == PF_BC4_UNSIGNED \
|| type == PF_BC5_SIGNED \
|| type == PF_BC5_UNSIGNED \
|| type == PF_BC6H_SIGNED \
|| type == PF_BC6H_UNSIGNED \
|| type == PF_BC7_UNORM \
|| type == PF_BC7_SRGB \
|| type == PF_KTX2_RAW )
#define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2 || type == PF_BC6H_SIGNED || type == PF_BC6H_UNSIGNED || type == PF_BC7)
typedef enum
{
@@ -38,15 +25,9 @@ typedef enum
PF_DXT3, // s3tc DXT3/BC2 format
PF_DXT5, // s3tc DXT5/BC3 format
PF_ATI2, // latc ATI2N/BC5 format
PF_BC4_SIGNED,
PF_BC4_UNSIGNED,
PF_BC5_SIGNED,
PF_BC5_UNSIGNED,
PF_BC6H_SIGNED, // bptc BC6H signed FP16 format
PF_BC6H_UNSIGNED, // bptc BC6H unsigned FP16 format
PF_BC7_UNORM, // bptc BC7 format
PF_BC7_SRGB,
PF_KTX2_RAW, // Raw KTX2 data, used for yet unsupported KTX2 subformats
PF_BC7, // bptc BC7 format
PF_TOTALCOUNT, // must be last
} pixformat_t;
@@ -69,7 +50,6 @@ typedef enum
IL_LOAD_DECAL = BIT(5), // special mode for load gradient decals
IL_OVERVIEW = BIT(6), // overview required some unque operations
IL_LOAD_PLAYER_DECAL = BIT(7), // special mode for player decals
IL_KTX2_RAW = BIT(8), // renderer can consume raw KTX2 files (e.g. ref_vk)
} ilFlags_t;
// goes into rgbdata_t->encode

View File

@@ -534,14 +534,5 @@ typedef struct
#define MAX_EFRAGS 8192 // Arcane Dimensions required
#define MAX_REQUESTS 64
#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

@@ -717,7 +717,6 @@ enum
kRenderFxExplode, // Scale up really big!
kRenderFxGlowShell, // Glowing Shell
kRenderFxClampMinScale, // Keep this sprite from getting very small (SPRITES only!)
kRenderFxLightMultiplier,
};
typedef int func_t;

View File

@@ -52,6 +52,26 @@ SETUP BACKENDS DEFINITIONS
#endif
#endif // XASH_MESSAGEBOX
#endif
#elif XASH_ANDROID
// we are building for Android platform, use Android APIs
#ifndef XASH_VIDEO
#define XASH_VIDEO VIDEO_ANDROID
#endif // XASH_VIDEO
#ifndef XASH_INPUT
#define XASH_INPUT INPUT_ANDROID
#endif // XASH_INPUT
#ifndef XASH_SOUND
#define XASH_SOUND SOUND_OPENSLES
#endif // XASH_SOUND
#ifndef XASH_MESSAGEBOX
#define XASH_MESSAGEBOX MSGBOX_ANDROID
#endif // XASH_MESSAGEBOX
#define XASH_USE_EVDEV 1
#define XASH_DYNAMIC_DLADDR
#elif XASH_LINUX
// we are building for Linux without SDL2, can draw only to framebuffer yet
#ifndef XASH_VIDEO
@@ -151,8 +171,6 @@ Default build-depended cvar and constant values
#define DEFAULT_MODE_WIDTH 960
#define DEFAULT_MODE_HEIGHT 544
#define DEFAULT_ALLOWCONSOLE 1
#elif XASH_ANDROID
#define DEFAULT_TOUCH_ENABLE "1"
#elif XASH_MOBILE_PLATFORM
#define DEFAULT_TOUCH_ENABLE "1"
#define DEFAULT_M_IGNORE "1"
@@ -186,11 +204,7 @@ Default build-depended cvar and constant values
#endif // DEFAULT_ALLOWCONSOLE
#ifndef DEFAULT_FULLSCREEN
#define DEFAULT_FULLSCREEN "1" // must be a string
#define DEFAULT_FULLSCREEN 1
#endif // DEFAULT_FULLSCREEN
#ifndef DEFAULT_MAX_EDICTS
#define DEFAULT_MAX_EDICTS 1200 // was 900 before HL25
#endif // DEFAULT_MAX_EDICTS
#endif // DEFAULTS_H

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,20 +27,4 @@ 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_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
#define ENGINE_FEATURES_MASK \
( ENGINE_WRITE_LARGE_COORD \
| ENGINE_QUAKE_COMPATIBLE \
| ENGINE_LOAD_DELUXEDATA \
| ENGINE_PHYSICS_PUSHER_EXT \
| ENGINE_LARGE_LIGHTMAPS \
| ENGINE_COMPENSATE_QUAKE_BUG \
| ENGINE_IMPROVED_LINETRACE \
| ENGINE_COMPUTE_STUDIO_LERP \
| ENGINE_LINEAR_GAMMA_SPACE \
| ENGINE_STEP_POSHISTORY_LERP )
#endif//FEATURES_H

View File

@@ -19,8 +19,6 @@ GNU General Public License for more details.
#define GFL_NOMODELS (1<<0)
#define GFL_NOSKILLS (1<<1)
#define GFL_RENDER_PICBUTTON_TEXT (1<<2)
#define GFL_HD_BACKGROUND (1<<3)
#define GFL_ANIMATED_TITLE (1<<4)
/*
========================================================================

View File

@@ -1,35 +1,18 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef KBUTTON_H
#define KBUTTON_H
// a1ba: copied from WinQuake/client.h
//========= Copyright © 1996-2002, Valve LLC, All rights reserved. ============
//
// cl_input
// Purpose:
//
typedef struct
// $NoKeywords: $
//=============================================================================
#if !defined( KBUTTONH )
#define KBUTTONH
#pragma once
typedef struct kbutton_s
{
int down[2]; // key nums holding it down
int state; // low bit is down state
} kbutton_t;
STATIC_ASSERT( sizeof( kbutton_t ) == 12, "kbutton_t isn't 12 bytes!" );
#endif // KBUTTON_H
#endif // !KBUTTONH

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

@@ -1,74 +1,76 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
/***
*
* 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.
*
****/
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef NET_ADR_H
#define NET_ADR_H
#ifndef NETADR_H
#define NETADR_H
#include "build.h"
#include STDINT_H
// net.h -- quake's interface to the networking layer
// a1ba: copied from Quake-2/qcommon/qcommon.h and modified to support IPv6
#define PORT_ANY -1
typedef enum {NA_LOOPBACK = 1, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX, NA_IP6, NA_MULTICAST_IP6} netadrtype_t;
/*
Original Quake-2 structure:
typedef struct
typedef enum
{
netadrtype_t type;
NA_UNUSED = 0,
NA_LOOPBACK,
NA_BROADCAST,
NA_IP,
NA_IPX,
NA_BROADCAST_IPX,
NA_IP6,
NA_MULTICAST_IP6, // all nodes multicast
} netadrtype_t;
byte ip[4];
byte ipx[10];
unsigned short port;
} netadr_t;
*/
// Original structure:
// typedef struct netadr_s
// {
// netadrtype_t type;
// unsigned char ip[4];
// unsigned char ipx[10];
// unsigned short port;
// } netadr_t;
#pragma pack( push, 1 )
typedef struct netadr_s
{
union
{
// IPv6 struct
struct
{
uint16_t type6;
uint8_t ip6[16];
};
struct
{
uint32_t type; // must be netadrtype_t but will break with short enums
uint32_t type;
union
{
uint8_t ip[4];
uint32_t ip4; // for easier conversions
uint8_t ip[4];
uint32_t ip4;
};
uint8_t ipx[10];
uint8_t ipx[10];
};
struct
{
#if XASH_LITTLE_ENDIAN
uint16_t type6;
uint8_t ip6[16];
#elif XASH_BIG_ENDIAN
uint8_t ip6_0[2];
uint16_t type6;
uint8_t ip6_2[14];
#endif
};
};
uint16_t port;
uint16_t port;
} netadr_t;
#pragma pack( pop )
STATIC_ASSERT( sizeof( netadr_t ) == 20, "netadr_t isn't 20 bytes!" );
STATIC_ASSERT( sizeof( netadr_t ) == 20, "invalid netadr_t size" );
#endif // NET_ADR_H
#endif//NETADR_H

View File

@@ -35,6 +35,7 @@ GNU General Public License for more details.
#define __cdecl
#define __stdcall
#define _inline static inline
#define FORCEINLINE inline __attribute__((always_inline))
#if XASH_POSIX
#include <unistd.h>
@@ -62,6 +63,13 @@ GNU General Public License for more details.
int x, y;
} POINT;
#else // WIN32
#ifdef __MINGW32__
#define _inline static inline
#define FORCEINLINE inline __attribute__((always_inline))
#else
#define FORCEINLINE __forceinline
#endif
#define open _open
#define read _read
#define alloca _alloca

View File

@@ -107,8 +107,7 @@ typedef enum
TF_ARB_FLOAT = (1<<26), // float textures
TF_NOCOMPARE = (1<<27), // disable comparing for depth textures
TF_ARB_16BIT = (1<<28), // keep image as 16-bit (not 24)
TF_MULTISAMPLE = (1<<29), // multisampling texture
TF_ALLOW_NEAREST = (1<<30), // allows toggling nearest filtering for TF_NOMIPMAP textures
TF_MULTISAMPLE = (1<<29) // multisampling texture
} texFlags_t;
typedef enum
@@ -230,7 +229,7 @@ typedef struct render_api_s
void (*R_Reserved0)( void );
// static allocations
void *(*pfnMemAlloc)( size_t cb, const char *filename, const int fileline ) ALLOC_CHECK( 1 );
void *(*pfnMemAlloc)( size_t cb, const char *filename, const int fileline );
void (*pfnMemFree)( void *mem, const char *filename, const int fileline );
// engine utils (not related with render API but placed here)

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
@@ -53,7 +57,9 @@ typedef uint64_t longtime_t;
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
#define BIT( n ) ( 1U << ( n ))
#define BIT64( n ) ( 1ULL << ( n ))
#define GAMMA ( 2.2f ) // Valve Software gamma
#define INVGAMMA ( 1.0f / 2.2f ) // back to 1.0
#define TEXGAMMA ( 0.9f ) // compensate dim textures
#define SetBits( iBitVector, bits ) ((iBitVector) = (iBitVector) | (bits))
#define ClearBits( iBitVector, bits ) ((iBitVector) = (iBitVector) & ~(bits))
#define FBitSet( iBitVector, bit ) ((iBitVector) & (bit))
@@ -70,72 +76,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 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 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))
#elif defined(_MSC_VER)
#define EXPORT __declspec( dllexport )
#define GAME_EXPORT
#define _format(x)
#define NORETURN
#else
#define EXPORT
#define GAME_EXPORT
#define _format(x)
#define NORETURN
#define NONNULL
#define _format( x )
#define ALLOC_CHECK( x )
#define RENAME_SYMBOL( 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 )
#endif
#if __STDC_VERSION__ >= 202311L || __cplusplus >= 201103L // C23 or C++ static_assert is a keyword
#define STATIC_ASSERT_( ignore, x, y ) static_assert( x, y )
#define STATIC_ASSERT static_assert
#elif __STDC_VERSION__ >= 201112L // in C11 it's _Static_assert
#define STATIC_ASSERT_( ignore, x, y ) _Static_assert( x, y )
#define STATIC_ASSERT _Static_assert
#else
#define STATIC_ASSERT_( id, x, y ) extern int id[( x ) ? 1 : -1]
// need these to correctly expand the line macro
#define STATIC_ASSERT_3( line, x, y ) STATIC_ASSERT_( static_assert_ ## line, x, y )
#define STATIC_ASSERT_2( line, x, y ) STATIC_ASSERT_3( line, x, y )
#define STATIC_ASSERT( x, y ) STATIC_ASSERT_2( __LINE__, x, y )
#define unlikely(x) (x)
#define likely(x) (x)
#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
#if defined( static_assert ) // C11 static_assert
#define STATIC_ASSERT static_assert
#else
#define XASH_RESTRICT // nothing
#define STATIC_ASSERT( x, y ) extern int _static_assert_##__LINE__[( x ) ? 1 : -1]
#endif
#ifdef XASH_BIG_ENDIAN
@@ -168,9 +150,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
@@ -196,7 +177,6 @@ typedef struct dll_info_s
} dll_info_t;
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
typedef void *(*pfnCreateInterface_t)( const char *, int * );
// config strings are a general means of communication from
// the server to all connected clients.

View File

@@ -0,0 +1,206 @@
#############################################
# Makefile.linux - linux makefile
# Copyright (C) 2017 mittorn
# 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.
##############################################
# Default options - optimized to debug on local machine
CC ?= gcc
CXX ?= g++
CFLAGS ?= -g -O1 -fsigned-char -Wall -Wextra -Wsign-compare -Wno-unknown-pragmas -Wno-missing-field-initializers -Wno-unused-parameter -Wno-unused-but-set-variable
LDFLAGS =
LBITS := $(shell getconf LONG_BIT)
DEPS :=
XASH_COMMIT := $(firstword $(shell git rev-parse --short=6 HEAD) unknown)
ifeq ($(XASH_COMMIT),unknown)
$(warning You seems to build xash3d without git)
$(warning Please use git if you are going to publish your build)
endif
# Pass 64BIT=1 to make arguments to allow amd64 builds
ifneq ($(64BIT),1)
ifeq ($(LBITS),64)
LDFLAGS += -m32
CFLAGS += -m32
endif
endif
TOPDIR = $(PWD)/..
INCLUDES :=
XASH_SINGLE_BINARY ?= 1
INSTALL_DIR ?= ./install/
ifeq ($(NANOGL),1)
INCLUDES += -Inanogl -Inanogl/GL
endif
INCLUDES += -I/usr/include/SDL2 -Icommon -I../common -I. -I../pm_shared -Iclient -Iserver -Iclient/vgui -Icommon/sdl
#############################
# Preprocessor defines:
#############################
DEFINES =
# Specify commit hash in version string
DEFINES += -DXASH_BUILD_COMMIT=\"$(XASH_COMMIT)\"
# Only SDL backend exists on linux
ifeq ($(XASH_DEDICATED),1)
DEFINES += -DXASH_DEDICATED
else
DEFINES += -DXASH_SDL
LIBS += -lSDL2
endif
#############################################
# GL/GLES translators.
# You need clone it to engine folder to use
# Only one translator should be enabled
#############################################
ifeq ($(NANOGL),1)
DEFINES += -DXASH_NANOGL -D__MULTITEXTURE_SUPPORT__ -DEGL_LIB=\"libEGL.so\"
endif
ifeq ($(WES),1)
DEFINES += -DXASH_WES -D__MULTITEXTURE_SUPPORT__ -DEGL_LIB=\"libEGL.so\"
endif
ifeq ($(REGAL),1)
DEFINES += -DXASH_REGAL -D__MULTITEXTURE_SUPPORT__ -DEGL_LIB=\"regal/lib/linux-32/libRegal.so\"
LIBS += regal/lib/linux-32/libRegal.so
endif
# Some libc implementations cannot use libdl in static builds, so disable it by default
ifeq ($(XASH_STATIC),1)
ifneq ($(XASH_STATIC_LIBDL),1)
DEFINES += -DNO_LIBDL
endif
XASH_SINGLE_BINARY := 1
endif
ifneq ($(XASH_STATIC),1)
LIBS += -ldl
endif
ifeq ($(XASH_STATIC_LIBDL),1)
LIBS += -ldl
endif
LIBS += -lm -pthread
ifeq ($(XASH_SINGLE_BINARY),1)
DEFINES += -DSINGLE_BINARY
endif
# Collect files
SRCS_CPP =
SRCS = $(wildcard server/*.c) $(wildcard client/vgui/*.c) $(wildcard client/avi/*.c) $(wildcard common/*.c) $(wildcard common/imagelib/*.c) $(wildcard common/soundlib/*.c) $(wildcard common/soundlib/libmpg/*.c)
ifneq ($(XASH_DEDICATED),1)
SRCS += $(wildcard client/*.c)
SRCS += $(wildcard platform/sdl/*.c)
ifeq ($(WES),1)
SRCS += $(wildcard gl-wes-v2/src/*.c)
endif
ifeq ($(NANOGL),1)
SRCS_CPP += $(wildcard nanogl/*.cpp)
endif
endif
OBJS = $(patsubst %.c,obj/%.o,$(SRCS))
OBJS_CPP = $(patsubst %.cpp,obj/%.o,$(SRCS_CPP))
#################################
# Windows DLL loader
# Should be enabled only on i386 builds
#################################
LOADER :=
ifeq ($(XASH_DLL_LOADER),1)
DEFINES += -DDLL_LOADER
ifeq ($(XASH_SINGLE_BINARY),1)
LOADER = libloader.a
else
LOADER = libloader.so
endif
DEPS += $(LOADER)
LIBS += $(LOADER)
endif
# Rules for binaries
ifeq ($(XASH_SINGLE_BINARY),0)
BINARIES = libxash.so
libxash.so : $(OBJS) $(OBJS_CPP) $(DEPS)
$(CC) -fvisibility=hidden -o libxash.so $(LDFLAGS) -shared $(OBJS) $(OBJS_CPP) $(LIBS)
else
BINARIES = xash
xash: $(OBJS) $(OBJS_CPP) $(DEPS)
ifeq ($(XASH_STATIC),1)
$(CC) -o xash -static $(LDFLAGS) $(OBJS) $(OBJS_CPP) $(LIBS)
else
$(CC) -o xash -fvisibility=hidden $(LDFLAGS) $(OBJS) $(OBJS_CPP) $(LIBS)
endif
endif
ifeq ($(XASH_DLL_LOADER),1)
$(LOADER):
$(MAKE) -f ../loader/Makefile.linux -C ../loader $(LOADER)
cp ../loader/$(LOADER) .
endif
# Create dirs for object files
DIRS := obj obj/server obj/client/avi obj/client/vgui obj/common/sdl obj/common/imagelib obj/common/soundlib/libmpg obj/platform/sdl obj/nanogl
$(OBJS): | $(DIRS)
$(DIRS) :
mkdir -p $(DIRS)
# Object rules
obj/%.o : %.c
$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) -c "$<" -o "$@" -Wno-unused-result -fvisibility=hidden
obj/%.o : %.cpp
$(CXX) $(CFLAGS) $(INCLUDES) $(DEFINES) -c "$<" -o "$@"
default: $(BINARIES)
.PHONY: depend clean list install
clean:
$(RM) $(OBJS) $(OBJS_CPP) $(BINARIES) ../loader/*.o ../loader/*.a ../loader/*.so $(LOADER)
list:
@echo Sources:
@echo $(SRCS)
@echo C++ Sources:
@echo $(SRCS_CPP)
@echo Objects:
@echo $(OBJS) $(OBJS_CPP)
@echo Dirs:
@echo $(DIRS)
@echo Dependencies:
@echo $(DEPS)
# Simple install rule
install: $(BINARIES)
mkdir -p $(INSTALL_DIR)
ifeq ($(XASH_SINGLE_BINARY),1)
cp xash $(INSTALL_DIR)/xash_bin
else
cp libxash.so $(INSTALL_DIR)/
cp libloader.so $(INSTALL_DIR)/
endif

269
contrib/mittorn/README.md Normal file
View File

@@ -0,0 +1,269 @@
**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
- [Building](#building)
- [Manual build (without CMake)](#manual-build-without-cmake)
- [Building Engine](#building-engine)
- [Building launch binary](#building-launch-binary)
- [Building on Windows](#building-on-windows)
- [Visual Studio 2013 (recommended for Windows)](#visual-studio-2013-recommended-for-windows)
- [Visual Studio 6](#visual-studio-6)
- [MinGW](#mingw)
- [Building Game mods](#building-game-mods)
- [Linux](#linux)
- [microndk](#microndk)
- [Makefile.linux](#makefile-linux)
- [Windows](#windows)
- [Running](#running)
- [Manual running](#manual-running)
- [Running with GDB](#running-with-gdb)
- [Using DLL Loader](#using-dll-loader)
- [Running MinGW builds](#running-mingw-builds)
- [Running MinGW builds under GDB](#running-mingw-builds-under-gdb)
# Building
## Manual build (without CMake)
### Building engine
Clone Xash3D repository using git:
git clone https://github.com/FWGS/xash3d
Move to the Xash3D folder:
cd xash3d/engine
make -f Makefile.linux XASH_VGUI=1
or same for dedicated
make -f Makefile.linux XASH_DEDICATED=1
To enable dll support on linux, build loader library:
cd ../loader
make -f Makefile.linux libloader.so libloader.a
cp libloader.so libloader.a ../engine/
And built engine with XASH_DLL_LOADER=1:
cd ../engine
make -f Makefile.linux XASH_VGUI=1 XASH_SDL=1 XASH_DLL_LOADER=1
or same for dedicated server
cd ../engine
make -f Makefile.linux XASH_DEDICATED=1 XASH_DLL_LOADER=1
### Building engine in separate library
Some old distros does not support hidden symbol visibility
This results in crash when loading server library
Building launch binary
cd (xash3d)/game_launch
gcc xash.c -o xash -ldl -lrt -lm
Building engine library:
make -f Makefile.linux XASH_SINGLE_BINARY=0
## Building on Windows
### Visual Studio 2013 (recommended for Windows)
Download latest prebuilt SDL2 from
https://www.libsdl.org/release/SDL2-devel-2.0.4-VC.zip
Unzip and rename `SDL2-2.0.4` folder to `SDL2` and put it next to xash3d project folder.
..\xash3d\
..\SDL2\
Open `xash.sln` with Visual Studio 2013 and make a build. After building, copy contents of `Debug` or
`Release` folder to directory you choose. Copy `valve` folder and `vgui.dll` from your Half Life game
installation folder and `SDL2.dll` form `\SDL2\lib\x86\` to it.
Move `vgui_support.dll` into `valve` folder.
..\valve\
..\valve\vgui_support.dll
..\menu.dll
..\SDL2.dll
..\vgui.dll
..\xash.dll
..\xash.exe
Now you good to go, just run `xash.exe`.
### Visual Studio 6
This is legacy configuration, but msvc6 seems to generate more stable and more effective code
Setup your msvc6 enviroment, unpack SDL2-2.0.4 to xash3d folder and do:
cd (xash3d)\engine
..\msvc6\build.bat
cd (xash3d)\game_launch
..\msvc6\build_launch.bat
### MinGW
The most effective configuration, but maybe unstable.
Setup your MinGW environment and run:
cd (xash3d)\engine\
CC=gcc mingw32-make -f Makefile.mingw
engine will be built to single exe binary
## Building game mods
### Linux
#### microndk
All mods that ported to android may be build to linux using Android.mk with microndk:
[https://github.com/SDLash3D/microndk]
Clone microndk repo somewhere, change xash3d_config to preffered configuration (change arch to x86
for example)
Go to dlls folder if you are building server or cl_dlls if you are building client and do:
make -f /path/to/microndk/microndk.mk -j4
Do:
make -f /path/to/microndk/microndk.mk -j4 clean
every time when you build client after building server
#### Makefile.linux
### Windows
On windows common way is using Visual Studio as many mods does not correctly work with mingw.
Just open project and build it.
Other is using mingw and microndk, but it was not tested yet.
hlsdk-xash3d based mods may work fine with mingw.
You may use microndk to build it. Build process is very similar to linux one.
After setting up MinGW enviroment, do:<br>
`mingw32-make -f \path\to\microndk\Microndk.mk`
to build 64-bit library, use:<br>
`mingw32-make -f \path\to\microndk\Microndk.mk 64BIT=1`
Edit xash3d_config.mk to set optimal CFLAGS if you are running server
# Running
Copy **valve** folder from Half-Life:
cp -r $HOME/.steam/steam/steamapps/common/Half-Life/valve $HOME/Games/Xash3D
**NOTE**: If you build with CMake, you can now use `make install`. It will install binaries where
they must be located. So just run `xash3d` from command line in directory where is gamedata is located.
For additional info look to the CMakeLists.txt in repo root and xash3d.sh script.
After a successful build, copy the next files to some other directory where you want to run Xash3D:
cp engine/libxash.so game_launch/xash3d mainui/libxashmenu.so $HOME/Games/Xash3D
If you built it with XASH_VGUI, also copy vgui.so:
cp ../hlsdk/linux/vgui.so vgui_support/libvgui_support.so $HOME/Games/Xash3D
Copy script:
cp ../xash3d.sh $HOME/Games/Xash3D
Run:
cd $HOME/Games/Xash3D
./xash3d.sh
## Manual running
Put xash3d binaries and vgui(optionally) to you game data directory and run:
LD_LIBRARY_PATH=. ./xash -dev 5
## Running under GDB
LD_LIBRARY_PATH=. gdb --args ./xash -dev 5
## Using DLL Loader
Put vgui_support.dll from windows build to your game data folder and run:
LD_LIBRARY_PATH=. ./xash -dev 5 -vguilib vgui.dll -clientlib valve/cl_dlls/client.dll -dll dlls/hl.dll
## Running MinGW builds
Put exe file to your game data directory
cd (game)\
xash_bin -dev 5
### Running MinGW builds under GDB
gdb --args ./xash_bin.exe -dev 5
# Useful GDB commands
Start or restart process:
(gdb) r
Show backtrace:
(gdb) bt
Full backtrace:
(gdb) bt full
Continue execution:
(gdb) c
Recover from segmentation fault:
Skipping function:
(gdb) handle SIGSEGV nopass
(gdb) ret
(gdb) c
Restart frame for beginning:
(gdb) handle SIGSEGV nopass
(gdb) jump *Host_AbortCurrentFrame
Anti-Crash script (useful for scripting servers):
```
cd /path/to/rootdir
file xash
set args xash -dev 5 -nowcon
handle SIGSEGV nopass
catch signal SIGSEGV
set $crashes=0
commands
print $crashes++
if $crashes > 500
set $crashes=0
run
else
jump *Host_AbortCurrentFrame
end
end
run
```

7
contrib/mittorn/setup.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
SCRIPTDIR=$(dirname "$0")
TOPDIR=$SCRIPTDIR/../../
cp $SCRIPTDIR/Makefile.dllloader $TOPDIR/loader/
cp $SCRIPTDIR/Makefile.emscripten $TOPDIR/engine/
cp $SCRIPTDIR/Makefile.linux $TOPDIR/engine/
cp $SCRIPTDIR/wscript $TOPDIR/engine/

73
contrib/mittorn/wscript Normal file
View File

@@ -0,0 +1,73 @@
#! /usr/bin/env python
# encoding: utf-8
# mittorn, 2018
VERSION='0.99'
APPNAME='xash3d-fwgs'
top = '.'
def options(opt):
opt.load('compiler_c')
# opt.load('msvs')
opt.add_option('--dedicated', action = 'store_true', help = 'build dedicated server only' )
opt.add_option('--64bits', dest = 'amd64', action = 'store_true', help = 'build 64-bit engine on x86_64' )
def configure(conf):
conf.load('compiler_c')
conf.env.append_unique('CFLAGS', '-O2')
conf.env.append_unique('DEFINES', 'SINGLE_BINARY')
conf.env.append_value('LINKFLAGS', '-ldl')
conf.env.append_value('LINKFLAGS', '-lm')
conf.env.append_value('LINKFLAGS', '-pthread')
# check for 64-bit builds
# TODO: check 32-bit toolchain and dependencies
if conf.env.DEST_CPU == 'x86_64' and not conf.options.amd64:
conf.env.append_value('LINKFLAGS', '-m32')
conf.env.append_value('CFLAGS', '-m32')
print('NOTE: will build engine with 64-bit toolchain using -m32')
else:
print('Warning: 64bit engine may be unstable')
# check for dedicated server build
if conf.options.dedicated:
conf.env.append_unique('DEFINES', 'XASH_DEDICATED')
conf.env.dedicated = True
else:
# TODO: add way to specify SDL2 path, move to separate function
try:
conf.check_cfg(path='sdl2-config', args='--cflags --libs', package='', msg='Checking for SDL2', uselib_store='SDL2')
except conf.errors.ConfigurationError:
conf.fatal('SDL2 not availiable! If you want to build dedicated server, specify --dedicated')
conf.env.append_unique('DEFINES', 'XASH_SDL')
def build(bld):
# basic build: dedicated only, no dependencies
use = [];
source = bld.path.ant_glob([
'common/*.c',
'common/imagelib/*.c',
'common/soundlib/*.c',
'common/soundlib/libmpg/*.c',
'server/*.c'])
# add client files and sdl2 library
if not bld.env.dedicated:
use += ['SDL2']
source += bld.path.ant_glob([
'client/*.c',
'client/vgui/*.c',
'client/avi/*.c',
'platform/sdl/*.c'])
bld(
target = 'xash',
features = 'c cprogram',
includes = ['../common', '../pm_shared', 'common', 'server', 'client', 'client/vgui', '.' ],
source = source,
use = use
)

View File

@@ -1,181 +1,177 @@
/*
Copyright (C) 1996-1997 Id Software, Inc.
/***
*
* 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.
*
****/
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
{-0.525731, 0.000000, 0.850651},
{-0.442863, 0.238856, 0.864188},
{-0.295242, 0.000000, 0.955423},
{-0.309017, 0.500000, 0.809017},
{-0.162460, 0.262866, 0.951056},
{0.000000, 0.000000, 1.000000},
{0.000000, 0.850651, 0.525731},
{-0.147621, 0.716567, 0.681718},
{0.147621, 0.716567, 0.681718},
{0.000000, 0.525731, 0.850651},
{0.309017, 0.500000, 0.809017},
{0.525731, 0.000000, 0.850651},
{0.295242, 0.000000, 0.955423},
{0.442863, 0.238856, 0.864188},
{0.162460, 0.262866, 0.951056},
{-0.681718, 0.147621, 0.716567},
{-0.809017, 0.309017, 0.500000},
{-0.587785, 0.425325, 0.688191},
{-0.850651, 0.525731, 0.000000},
{-0.864188, 0.442863, 0.238856},
{-0.716567, 0.681718, 0.147621},
{-0.688191, 0.587785, 0.425325},
{-0.500000, 0.809017, 0.309017},
{-0.238856, 0.864188, 0.442863},
{-0.425325, 0.688191, 0.587785},
{-0.716567, 0.681718, -0.147621},
{-0.500000, 0.809017, -0.309017},
{-0.525731, 0.850651, 0.000000},
{0.000000, 0.850651, -0.525731},
{-0.238856, 0.864188, -0.442863},
{0.000000, 0.955423, -0.295242},
{-0.262866, 0.951056, -0.162460},
{0.000000, 1.000000, 0.000000},
{0.000000, 0.955423, 0.295242},
{-0.262866, 0.951056, 0.162460},
{0.238856, 0.864188, 0.442863},
{0.262866, 0.951056, 0.162460},
{0.500000, 0.809017, 0.309017},
{0.238856, 0.864188, -0.442863},
{0.262866, 0.951056, -0.162460},
{0.500000, 0.809017, -0.309017},
{0.850651, 0.525731, 0.000000},
{0.716567, 0.681718, 0.147621},
{0.716567, 0.681718, -0.147621},
{0.525731, 0.850651, 0.000000},
{0.425325, 0.688191, 0.587785},
{0.864188, 0.442863, 0.238856},
{0.688191, 0.587785, 0.425325},
{0.809017, 0.309017, 0.500000},
{0.681718, 0.147621, 0.716567},
{0.587785, 0.425325, 0.688191},
{0.955423, 0.295242, 0.000000},
{1.000000, 0.000000, 0.000000},
{0.951056, 0.162460, 0.262866},
{0.850651, -0.525731, 0.000000},
{0.955423, -0.295242, 0.000000},
{0.864188, -0.442863, 0.238856},
{0.951056, -0.162460, 0.262866},
{0.809017, -0.309017, 0.500000},
{0.681718, -0.147621, 0.716567},
{0.850651, 0.000000, 0.525731},
{0.864188, 0.442863, -0.238856},
{0.809017, 0.309017, -0.500000},
{0.951056, 0.162460, -0.262866},
{0.525731, 0.000000, -0.850651},
{0.681718, 0.147621, -0.716567},
{0.681718, -0.147621, -0.716567},
{0.850651, 0.000000, -0.525731},
{0.809017, -0.309017, -0.500000},
{0.864188, -0.442863, -0.238856},
{0.951056, -0.162460, -0.262866},
{0.147621, 0.716567, -0.681718},
{0.309017, 0.500000, -0.809017},
{0.425325, 0.688191, -0.587785},
{0.442863, 0.238856, -0.864188},
{0.587785, 0.425325, -0.688191},
{0.688191, 0.587785, -0.425325},
{-0.147621, 0.716567, -0.681718},
{-0.309017, 0.500000, -0.809017},
{0.000000, 0.525731, -0.850651},
{-0.525731, 0.000000, -0.850651},
{-0.442863, 0.238856, -0.864188},
{-0.295242, 0.000000, -0.955423},
{-0.162460, 0.262866, -0.951056},
{0.000000, 0.000000, -1.000000},
{0.295242, 0.000000, -0.955423},
{0.162460, 0.262866, -0.951056},
{-0.442863, -0.238856, -0.864188},
{-0.309017, -0.500000, -0.809017},
{-0.162460, -0.262866, -0.951056},
{0.000000, -0.850651, -0.525731},
{-0.147621, -0.716567, -0.681718},
{0.147621, -0.716567, -0.681718},
{0.000000, -0.525731, -0.850651},
{0.309017, -0.500000, -0.809017},
{0.442863, -0.238856, -0.864188},
{0.162460, -0.262866, -0.951056},
{0.238856, -0.864188, -0.442863},
{0.500000, -0.809017, -0.309017},
{0.425325, -0.688191, -0.587785},
{0.716567, -0.681718, -0.147621},
{0.688191, -0.587785, -0.425325},
{0.587785, -0.425325, -0.688191},
{0.000000, -0.955423, -0.295242},
{0.000000, -1.000000, 0.000000},
{0.262866, -0.951056, -0.162460},
{0.000000, -0.850651, 0.525731},
{0.000000, -0.955423, 0.295242},
{0.238856, -0.864188, 0.442863},
{0.262866, -0.951056, 0.162460},
{0.500000, -0.809017, 0.309017},
{0.716567, -0.681718, 0.147621},
{0.525731, -0.850651, 0.000000},
{-0.238856, -0.864188, -0.442863},
{-0.500000, -0.809017, -0.309017},
{-0.262866, -0.951056, -0.162460},
{-0.850651, -0.525731, 0.000000},
{-0.716567, -0.681718, -0.147621},
{-0.716567, -0.681718, 0.147621},
{-0.525731, -0.850651, 0.000000},
{-0.500000, -0.809017, 0.309017},
{-0.238856, -0.864188, 0.442863},
{-0.262866, -0.951056, 0.162460},
{-0.864188, -0.442863, 0.238856},
{-0.809017, -0.309017, 0.500000},
{-0.688191, -0.587785, 0.425325},
{-0.681718, -0.147621, 0.716567},
{-0.442863, -0.238856, 0.864188},
{-0.587785, -0.425325, 0.688191},
{-0.309017, -0.500000, 0.809017},
{-0.147621, -0.716567, 0.681718},
{-0.425325, -0.688191, 0.587785},
{-0.162460, -0.262866, 0.951056},
{0.442863, -0.238856, 0.864188},
{0.162460, -0.262866, 0.951056},
{0.309017, -0.500000, 0.809017},
{0.147621, -0.716567, 0.681718},
{0.000000, -0.525731, 0.850651},
{0.425325, -0.688191, 0.587785},
{0.587785, -0.425325, 0.688191},
{0.688191, -0.587785, 0.425325},
{-0.955423, 0.295242, 0.000000},
{-0.951056, 0.162460, 0.262866},
{-1.000000, 0.000000, 0.000000},
{-0.850651, 0.000000, 0.525731},
{-0.955423, -0.295242, 0.000000},
{-0.951056, -0.162460, 0.262866},
{-0.864188, 0.442863, -0.238856},
{-0.951056, 0.162460, -0.262866},
{-0.809017, 0.309017, -0.500000},
{-0.864188, -0.442863, -0.238856},
{-0.951056, -0.162460, -0.262866},
{-0.809017, -0.309017, -0.500000},
{-0.681718, 0.147621, -0.716567},
{-0.681718, -0.147621, -0.716567},
{-0.850651, 0.000000, -0.525731},
{-0.688191, 0.587785, -0.425325},
{-0.587785, 0.425325, -0.688191},
{-0.425325, 0.688191, -0.587785},
{-0.425325, -0.688191, -0.587785},
{-0.587785, -0.425325, -0.688191},
{-0.688191, -0.587785, -0.425325},
{-0.525731, 0.000000, 0.850651},
{-0.442863, 0.238856, 0.864188},
{-0.295242, 0.000000, 0.955423},
{-0.309017, 0.500000, 0.809017},
{-0.162460, 0.262866, 0.951056},
{0.000000, 0.000000, 1.000000},
{0.000000, 0.850651, 0.525731},
{-0.147621, 0.716567, 0.681718},
{0.147621, 0.716567, 0.681718},
{0.000000, 0.525731, 0.850651},
{0.309017, 0.500000, 0.809017},
{0.525731, 0.000000, 0.850651},
{0.295242, 0.000000, 0.955423},
{0.442863, 0.238856, 0.864188},
{0.162460, 0.262866, 0.951056},
{-0.681718, 0.147621, 0.716567},
{-0.809017, 0.309017, 0.500000},
{-0.587785, 0.425325, 0.688191},
{-0.850651, 0.525731, 0.000000},
{-0.864188, 0.442863, 0.238856},
{-0.716567, 0.681718, 0.147621},
{-0.688191, 0.587785, 0.425325},
{-0.500000, 0.809017, 0.309017},
{-0.238856, 0.864188, 0.442863},
{-0.425325, 0.688191, 0.587785},
{-0.716567, 0.681718, -0.147621},
{-0.500000, 0.809017, -0.309017},
{-0.525731, 0.850651, 0.000000},
{0.000000, 0.850651, -0.525731},
{-0.238856, 0.864188, -0.442863},
{0.000000, 0.955423, -0.295242},
{-0.262866, 0.951056, -0.162460},
{0.000000, 1.000000, 0.000000},
{0.000000, 0.955423, 0.295242},
{-0.262866, 0.951056, 0.162460},
{0.238856, 0.864188, 0.442863},
{0.262866, 0.951056, 0.162460},
{0.500000, 0.809017, 0.309017},
{0.238856, 0.864188, -0.442863},
{0.262866, 0.951056, -0.162460},
{0.500000, 0.809017, -0.309017},
{0.850651, 0.525731, 0.000000},
{0.716567, 0.681718, 0.147621},
{0.716567, 0.681718, -0.147621},
{0.525731, 0.850651, 0.000000},
{0.425325, 0.688191, 0.587785},
{0.864188, 0.442863, 0.238856},
{0.688191, 0.587785, 0.425325},
{0.809017, 0.309017, 0.500000},
{0.681718, 0.147621, 0.716567},
{0.587785, 0.425325, 0.688191},
{0.955423, 0.295242, 0.000000},
{1.000000, 0.000000, 0.000000},
{0.951056, 0.162460, 0.262866},
{0.850651, -0.525731, 0.000000},
{0.955423, -0.295242, 0.000000},
{0.864188, -0.442863, 0.238856},
{0.951056, -0.162460, 0.262866},
{0.809017, -0.309017, 0.500000},
{0.681718, -0.147621, 0.716567},
{0.850651, 0.000000, 0.525731},
{0.864188, 0.442863, -0.238856},
{0.809017, 0.309017, -0.500000},
{0.951056, 0.162460, -0.262866},
{0.525731, 0.000000, -0.850651},
{0.681718, 0.147621, -0.716567},
{0.681718, -0.147621, -0.716567},
{0.850651, 0.000000, -0.525731},
{0.809017, -0.309017, -0.500000},
{0.864188, -0.442863, -0.238856},
{0.951056, -0.162460, -0.262866},
{0.147621, 0.716567, -0.681718},
{0.309017, 0.500000, -0.809017},
{0.425325, 0.688191, -0.587785},
{0.442863, 0.238856, -0.864188},
{0.587785, 0.425325, -0.688191},
{0.688191, 0.587785, -0.425325},
{-0.147621, 0.716567, -0.681718},
{-0.309017, 0.500000, -0.809017},
{0.000000, 0.525731, -0.850651},
{-0.525731, 0.000000, -0.850651},
{-0.442863, 0.238856, -0.864188},
{-0.295242, 0.000000, -0.955423},
{-0.162460, 0.262866, -0.951056},
{0.000000, 0.000000, -1.000000},
{0.295242, 0.000000, -0.955423},
{0.162460, 0.262866, -0.951056},
{-0.442863, -0.238856, -0.864188},
{-0.309017, -0.500000, -0.809017},
{-0.162460, -0.262866, -0.951056},
{0.000000, -0.850651, -0.525731},
{-0.147621, -0.716567, -0.681718},
{0.147621, -0.716567, -0.681718},
{0.000000, -0.525731, -0.850651},
{0.309017, -0.500000, -0.809017},
{0.442863, -0.238856, -0.864188},
{0.162460, -0.262866, -0.951056},
{0.238856, -0.864188, -0.442863},
{0.500000, -0.809017, -0.309017},
{0.425325, -0.688191, -0.587785},
{0.716567, -0.681718, -0.147621},
{0.688191, -0.587785, -0.425325},
{0.587785, -0.425325, -0.688191},
{0.000000, -0.955423, -0.295242},
{0.000000, -1.000000, 0.000000},
{0.262866, -0.951056, -0.162460},
{0.000000, -0.850651, 0.525731},
{0.000000, -0.955423, 0.295242},
{0.238856, -0.864188, 0.442863},
{0.262866, -0.951056, 0.162460},
{0.500000, -0.809017, 0.309017},
{0.716567, -0.681718, 0.147621},
{0.525731, -0.850651, 0.000000},
{-0.238856, -0.864188, -0.442863},
{-0.500000, -0.809017, -0.309017},
{-0.262866, -0.951056, -0.162460},
{-0.850651, -0.525731, 0.000000},
{-0.716567, -0.681718, -0.147621},
{-0.716567, -0.681718, 0.147621},
{-0.525731, -0.850651, 0.000000},
{-0.500000, -0.809017, 0.309017},
{-0.238856, -0.864188, 0.442863},
{-0.262866, -0.951056, 0.162460},
{-0.864188, -0.442863, 0.238856},
{-0.809017, -0.309017, 0.500000},
{-0.688191, -0.587785, 0.425325},
{-0.681718, -0.147621, 0.716567},
{-0.442863, -0.238856, 0.864188},
{-0.587785, -0.425325, 0.688191},
{-0.309017, -0.500000, 0.809017},
{-0.147621, -0.716567, 0.681718},
{-0.425325, -0.688191, 0.587785},
{-0.162460, -0.262866, 0.951056},
{0.442863, -0.238856, 0.864188},
{0.162460, -0.262866, 0.951056},
{0.309017, -0.500000, 0.809017},
{0.147621, -0.716567, 0.681718},
{0.000000, -0.525731, 0.850651},
{0.425325, -0.688191, 0.587785},
{0.587785, -0.425325, 0.688191},
{0.688191, -0.587785, 0.425325},
{-0.955423, 0.295242, 0.000000},
{-0.951056, 0.162460, 0.262866},
{-1.000000, 0.000000, 0.000000},
{-0.850651, 0.000000, 0.525731},
{-0.955423, -0.295242, 0.000000},
{-0.951056, -0.162460, 0.262866},
{-0.864188, 0.442863, -0.238856},
{-0.951056, 0.162460, -0.262866},
{-0.809017, 0.309017, -0.500000},
{-0.864188, -0.442863, -0.238856},
{-0.951056, -0.162460, -0.262866},
{-0.809017, -0.309017, -0.500000},
{-0.681718, 0.147621, -0.716567},
{-0.681718, -0.147621, -0.716567},
{-0.850651, 0.000000, -0.525731},
{-0.688191, 0.587785, -0.425325},
{-0.587785, 0.425325, -0.688191},
{-0.425325, 0.688191, -0.587785},
{-0.425325, -0.688191, -0.587785},
{-0.587785, -0.425325, -0.688191},
{-0.688191, -0.587785, -0.425325},

View File

@@ -85,12 +85,6 @@ void CL_PlayCDTrack_f( void )
paused = false;
looped = false;
}
else if( !Q_stricmp( command, "playfile" ))
{
S_StartBackgroundTrack( pszTrack, NULL, 0, true );
paused = false;
looped = false;
}
else if( !Q_stricmp( command, "loop" ))
{
if( Q_isdigit( pszTrack ))
@@ -102,12 +96,6 @@ void CL_PlayCDTrack_f( void )
paused = false;
looped = true;
}
else if( !Q_stricmp( command, "loopfile" ))
{
S_StartBackgroundTrack( pszTrack, pszTrack, 0, true );
paused = false;
looped = true;
}
else if( !Q_stricmp( command, "pause" ))
{
S_StreamSetPause( true );
@@ -157,12 +145,32 @@ void CL_PlayCDTrack_f( void )
CL_ScreenshotGetName
==================
*/
static qboolean CL_ScreenshotGetName( const char *fmt, int lastnum, char *filename, size_t size )
static qboolean CL_ScreenshotGetName( int lastnum, char *filename, size_t size )
{
if( lastnum < 0 || lastnum > 9999 )
{
Con_Printf( S_ERROR "unable to write screenshot\n" );
return false;
}
return Q_snprintf( filename, size, fmt, clgame.mapname, lastnum ) > 0;
return Q_snprintf( filename, size, "scrshots/%s_shot%04d.png", clgame.mapname, lastnum ) > 0;
}
/*
==================
CL_SnapshotGetName
==================
*/
static qboolean CL_SnapshotGetName( int lastnum, char *filename, size_t size )
{
if( lastnum < 0 || lastnum > 9999 )
{
Con_Printf( S_ERROR "unable to write snapshot\n" );
FS_AllowDirectPaths( false );
return false;
}
return Q_snprintf( filename, size, "../%s_%04d.png", clgame.mapname, lastnum ) > 0;
}
/*
@@ -172,6 +180,127 @@ static qboolean CL_ScreenshotGetName( const char *fmt, int lastnum, char *filena
==============================================================================
*/
/*
==================
CL_ScreenShot_f
normal screenshot
==================
*/
void CL_ScreenShot_f( void )
{
int i;
string checkname;
if( CL_IsDevOverviewMode() == 1 )
{
// special case for write overview image and script file
Q_snprintf( cls.shotname, sizeof( cls.shotname ), "overviews/%s.bmp", clgame.mapname );
cls.scrshot_action = scrshot_mapshot; // build new frame for mapshot
}
else
{
// scan for a free filename
for( i = 0; i < 9999; i++ )
{
if( !CL_ScreenshotGetName( i, checkname, sizeof( checkname )))
return; // no namespace
if( !FS_FileExists( checkname, false ))
break;
}
Q_strncpy( cls.shotname, checkname, sizeof( cls.shotname ));
cls.scrshot_action = scrshot_normal; // build new frame for screenshot
}
cls.envshot_vieworg = NULL; // no custom view
cls.envshot_viewsize = 0;
}
/*
==================
CL_SnapShot_f
save screenshots into root dir
==================
*/
void CL_SnapShot_f( void )
{
int i;
string checkname;
if( CL_IsDevOverviewMode() == 1 )
{
// special case for write overview image and script file
Q_snprintf( cls.shotname, sizeof( cls.shotname ), "overviews/%s.bmp", clgame.mapname );
cls.scrshot_action = scrshot_mapshot; // build new frame for mapshot
}
else
{
FS_AllowDirectPaths( true );
// scan for a free filename
for( i = 0; i < 9999; i++ )
{
if( !CL_SnapshotGetName( i, checkname, sizeof( checkname )))
return; // no namespace
if( !FS_FileExists( checkname, false ))
break;
}
FS_AllowDirectPaths( false );
Q_strncpy( cls.shotname, checkname, sizeof( cls.shotname ));
cls.scrshot_action = scrshot_snapshot; // build new frame for screenshot
}
cls.envshot_vieworg = NULL; // no custom view
cls.envshot_viewsize = 0;
}
/*
==================
CL_EnvShot_f
cubemap view
==================
*/
void CL_EnvShot_f( void )
{
if( Cmd_Argc() < 2 )
{
Con_Printf( S_USAGE "envshot <shotname>\n" );
return;
}
Q_snprintf( cls.shotname, sizeof( cls.shotname ), "gfx/env/%s", Cmd_Argv( 1 ));
cls.scrshot_action = scrshot_envshot; // build new frame for envshot
cls.envshot_vieworg = NULL; // no custom view
cls.envshot_viewsize = 0;
}
/*
==================
CL_SkyShot_f
skybox view
==================
*/
void CL_SkyShot_f( void )
{
if( Cmd_Argc() < 2 )
{
Con_Printf( S_USAGE "skyshot <shotname>\n" );
return;
}
Q_snprintf( cls.shotname, sizeof( cls.shotname ),"gfx/env/%s", Cmd_Argv( 1 ));
cls.scrshot_action = scrshot_skyshot; // build new frame for skyshot
cls.envshot_vieworg = NULL; // no custom view
cls.envshot_viewsize = 0;
}
/*
==================
CL_LevelShot_f
@@ -214,100 +343,23 @@ void CL_LevelShot_f( void )
else cls.scrshot_action = scrshot_inactive; // disable - not needs
}
static scrshot_t CL_GetScreenshotTypeFromString( const char *string )
/*
==================
CL_SaveShot_f
mini-pic in loadgame menu
==================
*/
void CL_SaveShot_f( void )
{
if( !Q_stricmp( string, "snapshot" ))
return scrshot_snapshot;
if( !Q_stricmp( string, "screenshot" ))
return scrshot_normal;
if( !Q_stricmp( string, "saveshot" ))
return scrshot_savegame;
if( !Q_stricmp( string, "envshot" ))
return scrshot_envshot;
if( !Q_stricmp( string, "skyshot" ))
return scrshot_skyshot;
return scrshot_inactive;
}
void CL_GenericShot_f( void )
{
const char *argv0 = Cmd_Argv( 0 );
scrshot_t type;
type = CL_GetScreenshotTypeFromString( argv0 );
if( type == scrshot_normal || type == scrshot_snapshot )
if( Cmd_Argc() < 2 )
{
if( CL_IsDevOverviewMode() == 1 )
type = scrshot_mapshot;
}
else
{
if( Cmd_Argc() < 2 )
{
Con_Printf( S_USAGE "%s <shotname>\n", argv0 );
return;
}
Con_Printf( S_USAGE "saveshot <savename>\n" );
return;
}
switch( type )
{
case scrshot_envshot:
case scrshot_skyshot:
Q_snprintf( cls.shotname, sizeof( cls.shotname ), "gfx/env/%s", Cmd_Argv( 1 ));
break;
case scrshot_savegame:
Q_snprintf( cls.shotname, sizeof( cls.shotname ), DEFAULT_SAVE_DIRECTORY "%s.bmp", Cmd_Argv( 1 ));
break;
case scrshot_mapshot:
Q_snprintf( cls.shotname, sizeof( cls.shotname ), "overviews/%s.bmp", clgame.mapname );
break;
case scrshot_normal:
case scrshot_snapshot:
{
const char *fmt;
string checkname;
int i;
if( type == scrshot_snapshot )
{
fmt = "../%s_%04d.png";
FS_AllowDirectPaths( true );
}
else fmt = "scrshots/%s_shot%04d.png";
for( i = 0; i < 9999; i++ )
{
if( !CL_ScreenshotGetName( fmt, i, checkname, sizeof( checkname )))
{
Con_Printf( S_ERROR "unable to write %s\n", argv0 );
FS_AllowDirectPaths( false );
return;
}
if( !FS_FileExists( checkname, true ))
break;
}
FS_AllowDirectPaths( false );
Q_strncpy( cls.shotname, checkname, sizeof( cls.shotname ));
break;
}
case scrshot_inactive:
case scrshot_plaque:
default:
return; // shouldn't happen
}
cls.scrshot_action = type; // build new frame for saveshot
cls.envshot_vieworg = NULL;
cls.envshot_viewsize = 0;
Q_snprintf( cls.shotname, sizeof( cls.shotname ), DEFAULT_SAVE_DIRECTORY "%s.bmp", Cmd_Argv( 1 ));
cls.scrshot_action = scrshot_savegame; // build new frame for saveshot
}
/*
@@ -349,7 +401,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;
}
@@ -128,7 +127,7 @@ void CL_MoveToOnHandList( resource_t *pResource )
CL_AddToResourceList( pResource, &cl.resourcesonhand );
}
static void CL_ClearResourceList( resource_t *pList )
void CL_ClearResourceList( resource_t *pList )
{
resource_t *p, *n;

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

@@ -107,42 +107,6 @@ struct
int angle_position;
} demo;
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;
}
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:
return PROTO_GOLDSRC;
}
return PROTO_CURRENT;
}
/*
====================
CL_StartupDemoHeader
@@ -153,8 +117,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 )
@@ -188,7 +156,7 @@ CL_GetDemoRecordClock
write time while demo is recording
====================
*/
static float CL_GetDemoRecordClock( void )
float CL_GetDemoRecordClock( void )
{
return cl.mtime[0];
}
@@ -200,7 +168,7 @@ CL_GetDemoPlaybackClock
overwrite host.realtime
====================
*/
static float CL_GetDemoPlaybackClock( void )
float CL_GetDemoPlaybackClock( void )
{
return host.realtime + host.frametime;
}
@@ -226,7 +194,7 @@ CL_WriteDemoCmdHeader
Writes the demo command header and time-delta
====================
*/
static void CL_WriteDemoCmdHeader( byte cmd, file_t *file )
void CL_WriteDemoCmdHeader( byte cmd, file_t *file )
{
float dt;
@@ -299,7 +267,7 @@ Save state of cls.netchan sequences
so that we can play the demo correctly.
====================
*/
static void CL_WriteDemoSequence( file_t *file )
void CL_WriteDemoSequence( file_t *file )
{
Assert( file != NULL );
@@ -380,7 +348,7 @@ CL_WriteDemoHeader
Write demo header
====================
*/
static void CL_WriteDemoHeader( const char *name )
void CL_WriteDemoHeader( const char *name )
{
int copysize;
int savepos;
@@ -403,8 +371,8 @@ 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.host_fps = host_maxfps.value ? bound( MIN_FPS, host_maxfps.value, MAX_FPS ) : MAX_FPS;
demo.header.net_protocol = cls.legacymode ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION;
demo.header.host_fps = bound( MIN_FPS, host_maxfps->value, MAX_FPS );
Q_strncpy( demo.header.mapname, clgame.mapname, sizeof( demo.header.mapname ));
Q_strncpy( demo.header.comment, clgame.maptitle, sizeof( demo.header.comment ));
Q_strncpy( demo.header.gamedir, FS_Gamedir(), sizeof( demo.header.gamedir ));
@@ -423,7 +391,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 );
@@ -469,7 +436,7 @@ CL_StopRecord
finish recording demo
=================
*/
static void CL_StopRecord( void )
void CL_StopRecord( void )
{
int i, curpos;
float stoptime;
@@ -551,7 +518,7 @@ CL_ReadDemoCmdHeader
read the demo command
=================
*/
static qboolean CL_ReadDemoCmdHeader( byte *cmd, float *dt )
qboolean CL_ReadDemoCmdHeader( byte *cmd, float *dt )
{
// read the command
// HACKHACK: skip NOPs
@@ -581,7 +548,7 @@ read the demo usercmd for predicting
and smooth movement during playback the demo
=================
*/
static void CL_ReadDemoUserCmd( qboolean discard )
void CL_ReadDemoUserCmd( qboolean discard )
{
byte data[1024];
int cmdnumber;
@@ -603,9 +570,6 @@ static void CL_ReadDemoUserCmd( qboolean discard )
memset( &nullcmd, 0, sizeof( nullcmd ));
MSG_Init( &buf, "UserCmd", data, sizeof( data ));
// a1ba: I have no proper explanation why
cmdnumber++;
pcmd = &cl.commands[cmdnumber & CL_UPDATE_MASK];
pcmd->processedfuncs = false;
pcmd->senttime = 0.0f;
@@ -646,7 +610,7 @@ CL_ReadDemoSequence
read netchan sequences
=================
*/
static void CL_ReadDemoSequence( qboolean discard )
void CL_ReadDemoSequence( qboolean discard )
{
int incoming_sequence;
int incoming_acknowledged;
@@ -680,17 +644,15 @@ static void CL_ReadDemoSequence( qboolean discard )
CL_DemoStartPlayback
=================
*/
static void CL_DemoStartPlayback( int mode )
void CL_DemoStartPlayback( int mode )
{
if( cls.changedemo )
{
int maxclients = cl.maxclients;
S_StopAllSounds( true );
SCR_BeginLoadingPlaque( false );
CL_ClearState( );
CL_InitEdicts( maxclients ); // re-arrange edicts
CL_ClearState ();
CL_InitEdicts (); // re-arrange edicts
}
else
{
@@ -725,7 +687,7 @@ static void CL_DemoStartPlayback( int mode )
CL_DemoAborted
=================
*/
static void CL_DemoAborted( void )
void CL_DemoAborted( void )
{
if( cls.demofile )
FS_Close( cls.demofile );
@@ -736,7 +698,7 @@ static void CL_DemoAborted( void )
cls.demofile = NULL;
cls.demonum = -1;
Cvar_DirectSet( &v_dark, "0" );
Cvar_SetValue( "v_dark", 0.0f );
}
/*
@@ -754,7 +716,7 @@ void CL_DemoCompleted( void )
if( !CL_NextDemo() && !cls.changedemo )
UI_SetActiveMenu( true );
Cvar_DirectSet( &v_dark, "0" );
Cvar_SetValue( "v_dark", 0.0f );
}
/*
@@ -765,7 +727,7 @@ returns true on success, false on failure
g-cont. probably captain obvious mode is ON
=================
*/
static qboolean CL_DemoMoveToNextSection( void )
qboolean CL_DemoMoveToNextSection( void )
{
if( ++demo.entryIndex >= demo.directory.numentries )
{
@@ -787,7 +749,7 @@ static qboolean CL_DemoMoveToNextSection( void )
return true;
}
static qboolean CL_ReadRawNetworkData( byte *buffer, size_t *length )
qboolean CL_ReadRawNetworkData( byte *buffer, size_t *length )
{
int msglen = 0;
@@ -838,7 +800,7 @@ CL_DemoReadMessageQuake
reads demo data and write it to client
=================
*/
static qboolean CL_DemoReadMessageQuake( byte *buffer, size_t *length )
qboolean CL_DemoReadMessageQuake( byte *buffer, size_t *length )
{
vec3_t viewangles;
int msglen = 0;
@@ -1053,7 +1015,7 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length )
return CL_ReadRawNetworkData( buffer, length );
}
static void CL_DemoFindInterpolatedViewAngles( float t, float *frac, demoangle_t **prev, demoangle_t **next )
void CL_DemoFindInterpolatedViewAngles( float t, float *frac, demoangle_t **prev, demoangle_t **next )
{
int i, i0, i1, imod;
float at;
@@ -1148,7 +1110,7 @@ CL_FinishTimeDemo
show stats
==============
*/
static void CL_FinishTimeDemo( void )
void CL_FinishTimeDemo( void )
{
int frames;
double time;
@@ -1160,10 +1122,7 @@ static void CL_FinishTimeDemo( void )
time = host.realtime - cls.td_starttime;
if( !time ) time = 1.0;
Con_Printf( "timedemo result: %i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
if( Sys_CheckParm( "-timedemo" ))
CL_Quit_f();
Con_Printf( "%i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
}
/*
@@ -1297,7 +1256,7 @@ CL_NextDemo
Called when a demo finishes
==================
*/
static qboolean CL_NextDemo( void )
qboolean CL_NextDemo( void )
{
char str[MAX_QPATH];
@@ -1347,7 +1306,7 @@ void CL_CheckStartupDemos( void )
}
// run demos loop in background mode
Cvar_DirectSet( &v_dark, "1" );
Cvar_SetValue( "v_dark", 1.0f );
cls.demos_pending = false;
cls.demonum = 0;
CL_NextDemo ();
@@ -1363,11 +1322,11 @@ static void CL_DemoGetName( int lastnum, char *filename, size_t size )
if( lastnum < 0 || lastnum > 9999 )
{
// bound
Q_strncpy( filename, "demo9999", size );
Q_strncpy( filename, "demo9999.dem", size );
return;
}
Q_snprintf( filename, size, "demo%04d", lastnum );
Q_snprintf( filename, size, "demo%04d.dem", lastnum );
}
/*
@@ -1422,9 +1381,7 @@ void CL_Record_f( void )
for( n = 0; n < 10000; n++ )
{
CL_DemoGetName( n, demoname, sizeof( demoname ));
Q_snprintf( demopath, sizeof( demopath ), "%s.dem", demoname );
if( !FS_FileExists( demopath, true ))
if( !FS_FileExists( demoname, true ))
break;
}
@@ -1511,7 +1468,7 @@ void CL_PlayDemo_f( void )
{
int c, neg = false;
demo.header.host_fps = host_maxfps.value;
demo.header.host_fps = host_maxfps->value;
while(( c = FS_Getc( cls.demofile )) != '\n' )
{
@@ -1520,7 +1477,6 @@ void CL_PlayDemo_f( void )
}
if( neg ) cls.forcetrack = -cls.forcetrack;
cls.legacymode = PROTO_QUAKE;
CL_DemoStartPlayback( DEMO_QUAKE1 );
return; // quake demo is started
}
@@ -1576,11 +1532,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
}
@@ -1622,7 +1576,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;
}

View File

@@ -6,7 +6,7 @@
#include "r_efx.h"
#include "cl_tent.h"
#include "pm_local.h"
#define PART_SIZE Q_max( 0.5f, cl_draw_particles.value )
#define PART_SIZE Q_max( 0.5f, cl_draw_particles->value )
/*
==============================================================
@@ -21,9 +21,9 @@ static int ramp2[8] = { 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66 };
static int ramp3[6] = { 0x6d, 0x6b, 6, 5, 4, 3 };
static int gSparkRamp[9] = { 0xfe, 0xfd, 0xfc, 0x6f, 0x6e, 0x6d, 0x6c, 0x67, 0x60 };
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" );
convar_t *tracerspeed;
convar_t *tracerlength;
convar_t *traceroffset;
particle_t *cl_active_particles;
particle_t *cl_active_tracers;
@@ -100,9 +100,9 @@ void CL_InitParticles( void )
cl_avelocities[i][2] = COM_RandomFloat( 0.0f, 2.55f );
}
Cvar_RegisterVariable( &tracerspeed );
Cvar_RegisterVariable( &tracerlength );
Cvar_RegisterVariable( &traceroffset );
tracerspeed = Cvar_Get( "tracerspeed", "6000", 0, "tracer speed" );
tracerlength = Cvar_Get( "tracerlength", "0.8", 0, "tracer length factor" );
traceroffset = Cvar_Get( "traceroffset", "30", 0, "tracer starting offset" );
}
/*
@@ -171,11 +171,11 @@ particle_t * GAME_EXPORT R_AllocParticle( void (*callback)( particle_t*, float )
{
particle_t *p;
if( !cl_draw_particles.value )
if( !cl_draw_particles->value )
return NULL;
// never alloc particles when we not in game
if( cl_clientframetime() == 0.0 ) return NULL;
// if( tr.frametime == 0.0 ) return NULL;
if( !cl_free_particles )
{
@@ -218,15 +218,15 @@ R_AllocTracer
can return NULL if particles is out
================
*/
static particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life )
particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life )
{
particle_t *p;
if( !cl_draw_tracers.value )
if( !cl_draw_tracers->value )
return NULL;
// never alloc particles when we not in game
if( cl_clientframetime() == 0.0 ) return NULL;
//if( tr.frametime == 0.0 ) return NULL;
if( !cl_free_particles )
{
@@ -249,7 +249,7 @@ static particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life
VectorCopy( org, p->org );
VectorCopy( vel, p->vel );
p->die = cl.time + life;
p->ramp = tracerlength.value;
p->ramp = tracerlength->value;
p->color = 4; // select custom color
p->packedColor = 255; // alpha
@@ -300,7 +300,7 @@ R_BeamAlloc
==============
*/
static BEAM *R_BeamAlloc( void )
BEAM *R_BeamAlloc( void )
{
BEAM *pBeam;
@@ -323,7 +323,7 @@ R_BeamFree
==============
*/
static void R_BeamFree( BEAM *pBeam )
void R_BeamFree( BEAM *pBeam )
{
// free particles that have died off.
R_FreeDeadParticles( &pBeam->particles );
@@ -605,7 +605,7 @@ CL_BeamAttemptToDie
Check for expired beams
==============
*/
static qboolean CL_BeamAttemptToDie( BEAM *pBeam )
qboolean CL_BeamAttemptToDie( BEAM *pBeam )
{
Assert( pBeam != NULL );
@@ -1236,15 +1236,12 @@ R_BloodStream
particle spray 2
===============
*/
void GAME_EXPORT R_BloodStream( const vec3_t org, const vec3_t ndir, int pcolor, int speed )
void GAME_EXPORT R_BloodStream( const vec3_t org, const vec3_t dir, int pcolor, int speed )
{
particle_t *p;
int i, j;
float arc;
int accel = speed; // must be integer due to bug in GoldSrc
vec3_t dir;
VectorNormalize2( ndir, dir );
for( arc = 0.05f, i = 0; i < 100; i++ )
{
@@ -1807,14 +1804,14 @@ void GAME_EXPORT R_TracerEffect( const vec3_t start, const vec3_t end )
float len, speed;
float offset;
speed = Q_max( tracerspeed.value, 3.0f );
speed = Q_max( tracerspeed->value, 3.0f );
VectorSubtract( end, start, dir );
len = VectorLength( dir );
if( len == 0.0f ) return;
VectorScale( dir, 1.0f / len, dir ); // normalize
offset = COM_RandomFloat( -10.0f, 9.0f ) + traceroffset.value;
offset = COM_RandomFloat( -10.0f, 9.0f ) + traceroffset->value;
VectorScale( dir, offset, vel );
VectorAdd( start, vel, pos );
VectorScale( dir, speed, vel );
@@ -2040,7 +2037,7 @@ void CL_ReadPointFile_f( void )
else Con_Printf( "map %s has no leaks!\n", clgame.mapname );
}
static void CL_FreeDeadBeams( void )
void CL_FreeDeadBeams( void )
{
BEAM *pBeam, *pNext, *pPrev = NULL;
// draw temporary entity beams
@@ -2070,16 +2067,16 @@ static void CL_FreeDeadBeams( void )
void CL_DrawEFX( float time, qboolean fTrans )
{
CL_FreeDeadBeams();
if( cl_draw_beams.value )
if( CVAR_TO_BOOL( cl_draw_beams ))
ref.dllFuncs.CL_DrawBeams( fTrans, cl_active_beams );
if( fTrans )
{
R_FreeDeadParticles( &cl_active_particles );
if( cl_draw_particles.value )
if( CVAR_TO_BOOL( cl_draw_particles ))
ref.dllFuncs.CL_DrawParticles( time, cl_active_particles, PART_SIZE );
R_FreeDeadParticles( &cl_active_tracers );
if( cl_draw_tracers.value )
if( CVAR_TO_BOOL( cl_draw_tracers ))
ref.dllFuncs.CL_DrawTracers( time, cl_active_tracers );
}
}

View File

@@ -40,7 +40,7 @@ CL_CalcPlayerVelocity
compute velocity for a given client
=============
*/
static void CL_CalcPlayerVelocity( int idx, vec3_t velocity )
void CL_CalcPlayerVelocity( int idx, vec3_t velocity )
{
clientdata_t *pcd;
vec3_t delta;
@@ -78,13 +78,13 @@ CL_DescribeEvent
=============
*/
static void CL_DescribeEvent( event_info_t *ei, int slot )
void CL_DescribeEvent( event_info_t *ei, int slot )
{
int idx = (slot & 63) * 2;
con_nprint_t info;
string origin_str = { 0 }; //, angles_str = { 0 };
if( !cl_showevents.value )
if( !cl_showevents->value )
return;
info.time_to_live = 1.0f;
@@ -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;
}
@@ -202,7 +202,7 @@ CL_FireEvent
=============
*/
static qboolean CL_FireEvent( event_info_t *ei, int slot )
qboolean CL_FireEvent( event_info_t *ei, int slot )
{
cl_user_event_t *ev;
const char *name;
@@ -219,24 +219,12 @@ 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;
}
if( ev->index == ei->index )
{
name = cl.event_precache[ei->index];
if( cl_trace_events.value )
{
Con_Printf( "^3EVENT %s AT %.2f %.2f %.2f\n" // event name
"\t%.2f %.2f %i %i %s %s\n", // bool params
name, ei->args.origin[0], ei->args.origin[1], ei->args.origin[2],
ei->args.fparam1, ei->args.fparam2,
ei->args.iparam1, ei->args.iparam2,
ei->args.bparam1 ? "TRUE" : "FALSE", ei->args.bparam2 ? "TRUE" : "FALSE" );
}
if( ev->func )
{
CL_DescribeEvent( ei, slot );
@@ -244,7 +232,8 @@ static qboolean CL_FireEvent( event_info_t *ei, int slot )
return true;
}
Con_Reportf( S_ERROR "%s: %s not hooked\n", __func__, name );
name = cl.event_precache[ei->index];
Con_Reportf( S_ERROR "CL_FireEvent: %s not hooked\n", name );
break;
}
}
@@ -292,7 +281,7 @@ CL_FindEvent
find first empty event
=============
*/
static event_info_t *CL_FindEmptyEvent( void )
event_info_t *CL_FindEmptyEvent( void )
{
int i;
event_state_t *es;
@@ -320,7 +309,7 @@ CL_FindEvent
replace only unreliable events
=============
*/
static event_info_t *CL_FindUnreliableEvent( void )
event_info_t *CL_FindUnreliableEvent( void )
{
event_state_t *es;
event_info_t *ei;
@@ -350,7 +339,7 @@ CL_QueueEvent
=============
*/
static void CL_QueueEvent( int flags, int index, float delay, event_args_t *args )
void CL_QueueEvent( int flags, int index, float delay, event_args_t *args )
{
event_info_t *ei;
@@ -497,14 +486,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

@@ -46,35 +46,10 @@ static int CL_LoadFontTexture( const char *fontname, uint texFlags, int *width )
return tex;
}
static int CL_FontRenderMode( convar_t *fontrender )
{
switch((int)fontrender->value )
{
case 0:
return kRenderTransAdd;
case 1:
return kRenderTransAlpha;
case 2:
return kRenderTransTexture;
default:
Cvar_DirectSet( fontrender, fontrender->def_string );
}
return kRenderTransTexture;
}
void CL_SetFontRendermode( cl_font_t *font )
{
ref.dllFuncs.GL_SetRenderMode( CL_FontRenderMode( font->rendermode ));
}
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags )
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags )
{
int font_width, i;
if( !rendermode )
return false;
if( font->valid )
return true; // already loaded
@@ -85,6 +60,7 @@ qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float sc
font->type = FONT_FIXED;
font->valid = true;
font->scale = scale;
font->nearest = FBitSet( texFlags, TF_NEAREST );
font->rendermode = rendermode;
font->charHeight = Q_rint( font_width / 16 * scale );
@@ -101,16 +77,13 @@ qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float sc
return true;
}
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags )
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags )
{
fs_offset_t length;
qfont_t src;
byte *pfile;
int font_width, i;
if( !rendermode )
return false;
if( font->valid )
return true;
@@ -133,7 +106,8 @@ qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float
font->type = FONT_VARIABLE;
font->valid = true;
font->scale = scale ? scale : 1.0f;
font->scale = scale;
font->nearest = FBitSet( texFlags, TF_NEAREST );
font->rendermode = rendermode;
font->charHeight = Q_rint( src.rowheight * scale );
@@ -205,8 +179,7 @@ int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *fon
return font->charWidths[number];
rc = &font->fontRc[number];
if( font->scale <= 1.f || !REF_GET_PARM( PARM_TEX_FILTERING, font->hFontTexture ))
if( font->nearest || font->scale <= 1.0f )
half = 0;
s1 = ((float)rc->left + half ) / texw;
@@ -220,7 +193,7 @@ int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *fon
SPR_AdjustSize( &x, &y, &w, &h );
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
CL_SetFontRendermode( font );
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
// don't apply color to fixed fonts it's already colored
if( font->type != FONT_FIXED || REF_GET_PARM( PARM_TEX_GLFORMAT, font->hFontTexture ) == 0x8045 ) // GL_LUMINANCE8_ALPHA8
@@ -243,7 +216,7 @@ int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *fon
Con_UtfProcessChar( 0 ); // clear utf state
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
CL_SetFontRendermode( font );
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
Vector4Copy( color, current_color );

View File

@@ -24,7 +24,7 @@ GNU General Public License for more details.
#include "sound.h"
#include "input.h"
// #define STUDIO_INTERPOLATION_FIX
#define STUDIO_INTERPOLATION_FIX
/*
==================
@@ -52,30 +52,19 @@ CL_UpdatePositions
Store another position into interpolation circular buffer
==================
*/
static void CL_UpdatePositions( cl_entity_t *ent )
void CL_UpdatePositions( cl_entity_t *ent )
{
position_history_t *ph, *prev;
prev = &ent->ph[ent->current_position];
position_history_t *ph;
ent->current_position = (ent->current_position + 1) & HISTORY_MASK;
ph = &ent->ph[ent->current_position];
VectorCopy( ent->curstate.origin, ph->origin );
VectorCopy( ent->curstate.angles, ph->angles );
ph->animtime = ent->curstate.animtime;
// a1ba: for some reason, this sometimes still may happen
// at this time, I'm not sure whether this bug happens in delta readwrite code
// or server just decides to go backwards and really sends these values
if( ph->animtime < prev->animtime )
{
// try to deduce real animtime by looking up the difference between
// server messages (cl.mtime is never modified ny the interpolation code)
float diff = Q_max( 0, ent->curstate.msg_time - ent->prevstate.msg_time );
ph->animtime = prev->animtime + diff;
}
if( ent->model && ent->model->type == mod_brush )
ph->animtime = ent->curstate.animtime;
else
ph->animtime = cl.time;
}
/*
@@ -85,7 +74,7 @@ CL_ResetPositions
Interpolation init or reset after teleporting
==================
*/
static void CL_ResetPositions( cl_entity_t *ent )
void CL_ResetPositions( cl_entity_t *ent )
{
position_history_t store;
@@ -107,7 +96,7 @@ check for instant movement in case
we don't want interpolate this
==================
*/
static qboolean CL_EntityTeleported( cl_entity_t *ent )
qboolean CL_EntityTeleported( cl_entity_t *ent )
{
float len, maxlen;
vec3_t delta;
@@ -128,7 +117,7 @@ CL_CompareTimestamps
round-off floating errors
==================
*/
static qboolean CL_CompareTimestamps( float t1, float t2 )
qboolean CL_CompareTimestamps( float t1, float t2 )
{
int iTime1 = t1 * 1000;
int iTime2 = t2 * 1000;
@@ -143,9 +132,9 @@ CL_EntityIgnoreLerp
some ents will be ignore lerping
==================
*/
static qboolean CL_EntityIgnoreLerp( cl_entity_t *e )
qboolean CL_EntityIgnoreLerp( cl_entity_t *e )
{
if( cl_nointerp.value > 0.f )
if( cl_nointerp->value > 0.f )
return true;
if( e->model && e->model->type == mod_alias )
@@ -160,7 +149,7 @@ CL_EntityCustomLerp
==================
*/
static qboolean CL_EntityCustomLerp( cl_entity_t *e )
qboolean CL_EntityCustomLerp( cl_entity_t *e )
{
switch( e->curstate.movetype )
{
@@ -170,13 +159,6 @@ static qboolean CL_EntityCustomLerp( cl_entity_t *e )
case MOVETYPE_FLY:
case MOVETYPE_COMPOUND:
return false;
// ABSOLUTELY STUPID HACK TO ALLOW MONSTERS
// INTERPOLATION IN GRAVGUNMOD COOP
// MUST BE REMOVED ONCE WE REMOVE 48 PROTO SUPPORT
case MOVETYPE_TOSS:
if( cls.legacymode && e->model && e->model->type == mod_studio )
return false;
}
return true;
@@ -189,7 +171,7 @@ CL_ParametricMove
check for parametrical moved entities
==================
*/
static qboolean CL_ParametricMove( cl_entity_t *ent )
qboolean CL_ParametricMove( cl_entity_t *ent )
{
float frac, dt, t;
vec3_t delta;
@@ -226,7 +208,7 @@ CL_UpdateLatchedVars
====================
*/
static void CL_UpdateLatchedVars( cl_entity_t *ent )
void CL_UpdateLatchedVars( cl_entity_t *ent )
{
if( !ent->model || ( ent->model->type != mod_alias && ent->model->type != mod_studio ))
return; // below fields used only for alias and studio interpolation
@@ -321,7 +303,7 @@ CL_ProcessEntityUpdate
apply changes since new frame received
==================
*/
static void CL_ProcessEntityUpdate( cl_entity_t *ent )
void CL_ProcessEntityUpdate( cl_entity_t *ent )
{
qboolean parametric;
@@ -367,10 +349,11 @@ CL_FindInterpolationUpdates
find two timestamps
==================
*/
static qboolean CL_FindInterpolationUpdates( cl_entity_t *ent, double targettime, position_history_t **ph0, position_history_t **ph1 )
qboolean CL_FindInterpolationUpdates( cl_entity_t *ent, float targettime, position_history_t **ph0, position_history_t **ph1 )
{
qboolean extrapolate = true;
uint i, i0, i1, imod;
float at;
imod = ent->current_position;
i0 = (imod - 0) & HISTORY_MASK; // curpos (lerp end)
@@ -378,10 +361,8 @@ static qboolean CL_FindInterpolationUpdates( cl_entity_t *ent, double targettime
for( i = 1; i < HISTORY_MAX - 1; i++ )
{
double at = ent->ph[( imod - i ) & HISTORY_MASK].animtime;
if( at == 0.0f )
break;
at = ent->ph[( imod - i ) & HISTORY_MASK].animtime;
if( at == 0.0f ) break;
if( targettime > at )
{
@@ -406,14 +387,15 @@ CL_PureOrigin
non-local players interpolation
==================
*/
static void CL_PureOrigin( cl_entity_t *ent, double t, vec3_t outorigin, vec3_t outangles )
void CL_PureOrigin( cl_entity_t *ent, float t, vec3_t outorigin, vec3_t outangles )
{
double t1, t0, frac;
qboolean extrapolate;
float t1, t0, frac;
position_history_t *ph0, *ph1;
vec3_t delta;
// NOTE: ph0 is next, ph1 is a prev
CL_FindInterpolationUpdates( ent, t, &ph0, &ph1 );
extrapolate = CL_FindInterpolationUpdates( ent, t, &ph0, &ph1 );
if ( !ph0 || !ph1 )
return;
@@ -421,7 +403,7 @@ static void CL_PureOrigin( cl_entity_t *ent, double t, vec3_t outorigin, vec3_t
t0 = ph0->animtime;
t1 = ph1->animtime;
if( t0 != 0.0 )
if( t0 != 0.0f )
{
vec4_t q, q1, q2;
@@ -429,9 +411,9 @@ static void CL_PureOrigin( cl_entity_t *ent, double t, vec3_t outorigin, vec3_t
if( !Q_equal( t0, t1 ))
frac = ( t - t1 ) / ( t0 - t1 );
else frac = 1.0;
else frac = 1.0f;
frac = bound( 0.0, frac, 1.2 );
frac = bound( 0.0f, frac, 1.2f );
VectorMA( ph1->origin, frac, delta, outorigin );
@@ -455,11 +437,11 @@ CL_InterpolateModel
non-players interpolation
==================
*/
static int CL_InterpolateModel( cl_entity_t *e )
int CL_InterpolateModel( cl_entity_t *e )
{
position_history_t *ph0 = NULL, *ph1 = NULL;
vec3_t origin, angles, delta;
double t, t1, t2, frac;
float t, t1, t2, frac;
vec4_t q, q1, q2;
VectorCopy( e->curstate.origin, e->origin );
@@ -482,13 +464,13 @@ static int CL_InterpolateModel( cl_entity_t *e )
if( cl.maxclients <= 1 )
return 1;
if( e->model->type == mod_brush && !cl_bmodelinterp.value )
if( e->model->type == mod_brush && !cl_bmodelinterp->value )
return 1;
if( cl.local.moving && cl.local.onground == e->index )
return 1;
t = cl.time - cl_interp.value;
t = cl.time - cl_interp->value;
CL_FindInterpolationUpdates( e, t, &ph0, &ph1 );
if( ph0 == NULL || ph1 == NULL )
@@ -507,7 +489,9 @@ static int CL_InterpolateModel( cl_entity_t *e )
return 0;
}
if( Q_equal( t2, t1 ))
// HACKHACK: workaround buggy position history animtime
// going backward sometimes
if( Q_equal( t2, t1 ) || t2 < t1 )
{
VectorCopy( ph0->origin, e->origin );
VectorCopy( ph0->angles, e->angles );
@@ -545,7 +529,7 @@ interpolate non-local clients
*/
void CL_ComputePlayerOrigin( cl_entity_t *ent )
{
double targettime;
float targettime;
vec4_t q, q1, q2;
vec3_t origin;
vec3_t angles;
@@ -553,7 +537,7 @@ void CL_ComputePlayerOrigin( cl_entity_t *ent )
if( !ent->player )
return;
if( cl_nointerp.value > 0.f )
if( cl_nointerp->value > 0.f )
{
VectorCopy( ent->curstate.angles, ent->angles );
VectorCopy( ent->curstate.origin, ent->origin );
@@ -571,7 +555,7 @@ void CL_ComputePlayerOrigin( cl_entity_t *ent )
return;
}
targettime = cl.time - cl_interp.value;
targettime = cl.time - cl_interp->value;
CL_PureOrigin( ent, targettime, origin, angles );
VectorCopy( angles, ent->angles );
@@ -585,7 +569,7 @@ CL_ProcessPlayerState
process player states after the new packet has received
=================
*/
static void CL_ProcessPlayerState( int playerindex, entity_state_t *state )
void CL_ProcessPlayerState( int playerindex, entity_state_t *state )
{
entity_state_t *ps;
@@ -605,7 +589,7 @@ reset latched state if this frame entity was teleported
or just EF_NOINTERP was set
=================
*/
static void CL_ResetLatchedState( int pnum, frame_t *frame, cl_entity_t *ent )
void CL_ResetLatchedState( int pnum, frame_t *frame, cl_entity_t *ent )
{
if( CHECKVISBIT( frame->flags, pnum ))
{
@@ -695,7 +679,7 @@ CL_FlushEntityPacket
Read and ignore whole entity packet.
=================
*/
static void CL_FlushEntityPacket( sizebuf_t *msg )
void CL_FlushEntityPacket( sizebuf_t *msg )
{
int newnum;
entity_state_t from, to;
@@ -712,7 +696,7 @@ static void CL_FlushEntityPacket( sizebuf_t *msg )
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] );
}
@@ -725,7 +709,7 @@ CL_DeltaEntity
processing delta update
=================
*/
static void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t *old, qboolean has_update )
void CL_DeltaEntity( sizebuf_t *msg, frame_t *frame, int newnum, entity_state_t *old, qboolean has_update )
{
cl_entity_t *ent;
entity_state_t *state;
@@ -740,7 +724,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;
@@ -885,7 +869,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
break; // done
if( MSG_CheckOverflow( msg ))
Host_Error( "%s: overflow\n", __func__ );
Host_Error( "CL_ParsePacketEntities: overflow\n" );
player = CL_IsPlayerIndex( newnum );
@@ -955,7 +939,7 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
}
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
@@ -1057,7 +1041,7 @@ CL_LinkCustomEntity
Add server beam to draw list
=============
*/
static void CL_LinkCustomEntity( cl_entity_t *ent, entity_state_t *state )
void CL_LinkCustomEntity( cl_entity_t *ent, entity_state_t *state )
{
ent->curstate.movetype = state->modelindex; // !!!
@@ -1080,7 +1064,7 @@ Create visible entities in the correct position
for all current players
=============
*/
static void CL_LinkPlayers( frame_t *frame )
void CL_LinkPlayers( frame_t *frame )
{
entity_state_t *state;
cl_entity_t *ent;
@@ -1163,7 +1147,7 @@ CL_LinkPacketEntities
===============
*/
static void CL_LinkPacketEntities( frame_t *frame )
void CL_LinkPacketEntities( frame_t *frame )
{
cl_entity_t *ent;
entity_state_t *state;
@@ -1187,7 +1171,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;
}
@@ -1228,33 +1212,17 @@ static void CL_LinkPacketEntities( frame_t *frame )
#else
if( ent->lastmove >= cl.time )
{
float at = ent->curstate.animtime;
CL_ResetLatchedVars( ent, true );
if( cl_fixmodelinterpolationartifacts.value )
ent->latched.prevanimtime = ent->curstate.animtime = at;
VectorCopy( ent->curstate.origin, ent->latched.prevorigin );
VectorCopy( ent->curstate.angles, ent->latched.prevangles );
if( !FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP ))
{
// disable step interpolation in client.dll
ent->curstate.movetype = MOVETYPE_NONE;
}
// disable step interpolation in client.dll
ent->curstate.movetype = MOVETYPE_NONE;
}
else
{
if( FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP ))
{
interpolate = true;
}
else
{
// restore step interpolation in client.dll
ent->curstate.movetype = MOVETYPE_STEP;
}
// restore step interpolation in client.dll
ent->curstate.movetype = MOVETYPE_STEP;
}
#endif
}
@@ -1279,24 +1247,11 @@ static void CL_LinkPacketEntities( frame_t *frame )
if ( !CL_InterpolateModel( ent ))
continue;
}
// a1ba: in GoldSrc this is done for cstrike and czero
// but let modders use this as an engine feature
else if( FBitSet( host.features, ENGINE_STEP_POSHISTORY_LERP ) &&
ent->curstate.movetype == MOVETYPE_STEP && !NET_IsLocalAddress( cls.netchan.remote_address ))
else if( ent->curstate.movetype == MOVETYPE_STEP && !NET_IsLocalAddress( cls.netchan.remote_address ))
{
if( !CL_InterpolateModel( ent ))
continue;
}
#if 0
// ABSOLUTELY STUPID HACK TO ALLOW MONSTERS
// INTERPOLATION IN GRAVGUNMOD COOP
// MUST BE REMOVED ONCE WE REMOVE 48 PROTO SUPPORT
else if( cls.legacymode && ent->model->type == mod_studio && ent->curstate.movetype == MOVETYPE_TOSS )
{
if( !CL_InterpolateModel( ent ))
continue;
}
#endif
else
{
// no interpolation right now
@@ -1492,3 +1447,9 @@ qboolean CL_GetMovieSpatialization( rawchan_t *ch )
return true;
}
void CL_ExtraUpdate( void )
{
clgame.dllFuncs.IN_Accumulate();
S_ExtraUpdate();
}

File diff suppressed because it is too large Load Diff

View File

@@ -216,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 )
@@ -416,15 +414,11 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
out->gamemode = in->gamemode;
if( in->nomodels )
SetBits( out->flags, GFL_NOMODELS );
out->flags |= GFL_NOMODELS;
if( in->noskills )
SetBits( out->flags, GFL_NOSKILLS );
out->flags |= GFL_NOSKILLS;
if( in->render_picbutton_text )
SetBits( out->flags, GFL_RENDER_PICBUTTON_TEXT );
if( in->hd_background )
SetBits( out->flags, GFL_HD_BACKGROUND );
if( in->animated_title )
SetBits( out->flags, GFL_ANIMATED_TITLE );
out->flags |= GFL_RENDER_PICBUTTON_TEXT;
}
/*
@@ -494,7 +488,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;
}
@@ -544,7 +538,7 @@ pfnPIC_Set
=========
*/
static void GAME_EXPORT pfnPIC_Set( HIMAGE hPic, int r, int g, int b, int a )
void GAME_EXPORT pfnPIC_Set( HIMAGE hPic, int r, int g, int b, int a )
{
gameui.ds.gl_texturenum = hPic;
r = bound( 0, r, 255 );
@@ -560,7 +554,7 @@ pfnPIC_Draw
=========
*/
static void GAME_EXPORT pfnPIC_Draw( int x, int y, int width, int height, const wrect_t *prc )
void GAME_EXPORT pfnPIC_Draw( int x, int y, int width, int height, const wrect_t *prc )
{
ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
PIC_DrawGeneric( x, y, width, height, prc );
@@ -572,7 +566,7 @@ pfnPIC_DrawTrans
=========
*/
static void GAME_EXPORT pfnPIC_DrawTrans( int x, int y, int width, int height, const wrect_t *prc )
void GAME_EXPORT pfnPIC_DrawTrans( int x, int y, int width, int height, const wrect_t *prc )
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
PIC_DrawGeneric( x, y, width, height, prc );
@@ -584,7 +578,7 @@ pfnPIC_DrawHoles
=========
*/
static void GAME_EXPORT pfnPIC_DrawHoles( int x, int y, int width, int height, const wrect_t *prc )
void GAME_EXPORT pfnPIC_DrawHoles( int x, int y, int width, int height, const wrect_t *prc )
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransAlpha );
PIC_DrawGeneric( x, y, width, height, prc );
@@ -596,7 +590,7 @@ pfnPIC_DrawAdditive
=========
*/
static void GAME_EXPORT pfnPIC_DrawAdditive( int x, int y, int width, int height, const wrect_t *prc )
void GAME_EXPORT pfnPIC_DrawAdditive( int x, int y, int width, int height, const wrect_t *prc )
{
ref.dllFuncs.GL_SetRenderMode( kRenderTransAdd );
PIC_DrawGeneric( x, y, width, height, prc );
@@ -648,17 +642,6 @@ static void GAME_EXPORT pfnFillRGBA( int x, int y, int width, int height, int r,
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
}
/*
=============
pfnCvar_RegisterVariable
=============
*/
static cvar_t *GAME_EXPORT pfnCvar_RegisterGameUIVariable( const char *szName, const char *szValue, int flags )
{
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_GAMEUIDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_GAMEUIDLL ));
}
/*
=============
pfnClientCmd
@@ -986,23 +969,30 @@ pfnCheckGameDll
=========
*/
static int GAME_EXPORT pfnCheckGameDll( void )
int GAME_EXPORT pfnCheckGameDll( void )
{
#ifdef XASH_INTERNAL_GAMELIBS
return true;
#else
string dllpath;
void *hInst;
#if TARGET_OS_IPHONE
// loading server library drains too many ram
// so 512MB iPod Touch cannot even connect to
// to servers in cstrike
return true;
#endif
if( svgame.hInstance )
return true;
COM_GetCommonLibraryPath( LIBRARY_SERVER, dllpath, sizeof( dllpath ));
if( FS_FileExists( dllpath, false ))
if(( hInst = COM_LoadLibrary( dllpath, true, false )) != NULL )
{
COM_FreeLibrary( hInst ); // don't increase linker's reference counter
return true;
}
Con_Reportf( S_WARN "Could not load server library: %s\n", COM_GetLibraryError() );
return false;
#endif
}
/*
@@ -1013,7 +1003,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" );
}
/*
@@ -1094,25 +1084,6 @@ static int pfnDelete( const char *path )
return FS_Delete( path );
}
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 ui_enginefuncs_t gEngfuncs =
{
@@ -1152,7 +1123,7 @@ static ui_enginefuncs_t gEngfuncs =
UI_DrawConsoleString,
UI_DrawSetTextColor,
Con_DrawStringLen,
pfnCon_DefaultColor,
Con_DefaultColor,
pfnGetPlayerModel,
pfnSetPlayerModel,
pfnClearScene,
@@ -1192,7 +1163,7 @@ static ui_enginefuncs_t gEngfuncs =
pfnHostEndGame,
COM_RandomFloat,
COM_RandomLong,
pfnSetCursor,
IN_SetCursor,
pfnIsMapValid,
GL_ProcessTexture,
COM_CompareFileTime,
@@ -1236,8 +1207,6 @@ static ui_extendedfuncs_t gExtendedfuncs =
pfnParseFileSafe,
NET_AdrToString,
NET_CompareAdrSort,
Sys_GetNativeObject,
&gNetApi,
};
void UI_UnloadProgs( void )
@@ -1249,12 +1218,12 @@ void UI_UnloadProgs( void )
Cvar_FullSet( "host_gameuiloaded", "0", FCVAR_READ_ONLY );
Cvar_Unlink( FCVAR_GAMEUIDLL );
Cmd_Unlink( CMD_GAMEUIDLL );
COM_FreeLibrary( gameui.hInstance );
Mem_FreePool( &gameui.mempool );
memset( &gameui, 0, sizeof( gameui ));
Cvar_Unlink( FCVAR_GAMEUIDLL );
Cmd_Unlink( CMD_GAMEUIDLL );
}
qboolean UI_LoadProgs( void )
@@ -1297,13 +1266,13 @@ 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
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
@@ -1313,7 +1282,7 @@ qboolean UI_LoadProgs( void )
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;
@@ -1326,30 +1295,30 @@ qboolean UI_LoadProgs( void )
// 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" );
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,17 +20,17 @@ GNU General Public License for more details.
#include "input.h"
#include "platform/platform.h"
static mobile_engfuncs_t *gMobileEngfuncs;
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" );
convar_t *vibration_length;
convar_t *vibration_enable;
static cl_font_t g_scaled_font;
static float g_font_scale;
static void pfnVibrate( float life, char flags )
{
if( !vibration_enable.value )
if( !vibration_enable->value )
return;
if( life < 0.0f )
@@ -42,7 +42,7 @@ static void pfnVibrate( float life, char flags )
//Con_Reportf( "Vibrate: %f %d\n", life, flags );
// here goes platform-specific backends
Platform_Vibrate( life * vibration_length.value, flags );
Platform_Vibrate( life * vibration_length->value, flags );
}
static void Vibrate_f( void )
@@ -67,7 +67,7 @@ static int pfnDrawScaledCharacter( int x, int y, int number, int r, int g, int b
rgba_t color = { r, g, b, 255 };
int flags = FONT_DRAW_HUD;
if( hud_utf8.value )
if( hud_utf8->value )
SetBits( flags, FONT_DRAW_UTF8 );
if( fabs( g_font_scale - scale ) > 0.1f ||
@@ -87,6 +87,15 @@ static int pfnDrawScaledCharacter( int x, int y, int number, int r, int g, int b
return CL_DrawCharacter( x, y, number, color, &g_scaled_font, flags );
}
static void *pfnGetNativeObject( const char *obj )
{
if( !obj )
return NULL;
// Backend should consider that obj is case-sensitive
return Platform_GetNativeObject( obj );
}
static void pfnTouch_HideButtons( const char *name, byte state )
{
Touch_HideButtons( name, state, true );
@@ -115,7 +124,7 @@ static mobile_engfuncs_t gpMobileEngfuncs =
Touch_ResetDefaultButtons,
pfnDrawScaledCharacter,
Sys_Warn,
Sys_GetNativeObject,
pfnGetNativeObject,
ID_SetCustomClientID,
pfnParseFileSafe
};
@@ -133,8 +142,8 @@ qboolean Mobile_Init( void )
success = true;
Cmd_AddCommand( "vibrate", (xcommand_t)Vibrate_f, "Vibrate for specified time");
Cvar_RegisterVariable( &vibration_length );
Cvar_RegisterVariable( &vibration_enable );
vibration_length = Cvar_Get( "vibration_length", "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "Vibration length");
vibration_enable = Cvar_Get( "vibration_enable", "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "Enable vibration");
return success;
}

View File

@@ -33,12 +33,12 @@ GNU General Public License for more details.
#define NETGRAPH_NET_COLORS 5
#define NUM_LATENCY_SAMPLES 8
CVAR_DEFINE_AUTO( net_graph, "0", FCVAR_ARCHIVE, "draw network usage graph" );
static CVAR_DEFINE_AUTO( net_graphpos, "1", FCVAR_ARCHIVE, "network usage graph position" );
static CVAR_DEFINE_AUTO( net_scale, "5", FCVAR_ARCHIVE, "network usage graph scale level" );
static CVAR_DEFINE_AUTO( net_graphwidth, "192", FCVAR_ARCHIVE, "network usage graph width" );
static CVAR_DEFINE_AUTO( net_graphheight, "64", FCVAR_ARCHIVE, "network usage graph height" );
static CVAR_DEFINE_AUTO( net_graphsolid, "1", FCVAR_ARCHIVE, "fill segments in network usage graph" );
convar_t *net_graph;
static convar_t *net_graphpos;
static convar_t *net_graphwidth;
static convar_t *net_graphheight;
static convar_t *net_graphsolid;
static convar_t *net_scale;
static struct packet_latency_t
{
@@ -211,7 +211,7 @@ static void NetGraph_GetFrameData( float *latency, int *latency_count )
else
{
int frame_latency = Q_min( 1.0f, f->latency );
p->latency = (( frame_latency + 0.1f ) / 1.1f ) * ( net_graphheight.value - NETGRAPH_LERP_HEIGHT - 2 );
p->latency = (( frame_latency + 0.1f ) / 1.1f ) * ( net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2 );
if( i > cls.netchan.incoming_sequence - NUM_LATENCY_SAMPLES )
{
@@ -260,7 +260,7 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
for( a = 0; a < w; a++ )
{
i = ( cls.netchan.outgoing_sequence - a ) & NET_TIMINGS_MASK;
h = Q_min(( netstat_cmdinfo[i].cmd_lerp / 3.0f ) * NETGRAPH_LERP_HEIGHT, net_graphheight.value * 0.7f);
h = Q_min(( netstat_cmdinfo[i].cmd_lerp / 3.0f ) * NETGRAPH_LERP_HEIGHT, net_graphheight->value * 0.7f);
fill.left = x + w - a - 1;
fill.right = fill.bottom = 1;
@@ -273,7 +273,7 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
h -= extrap_point;
fill.top -= extrap_point;
if( !net_graphsolid.value )
if( !net_graphsolid->value )
{
fill.top -= (h - 1);
start = (h - 1);
@@ -295,7 +295,7 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
fill.top -= h;
h = extrap_point - h;
if( !net_graphsolid.value )
if( !net_graphsolid->value )
h = 1;
for( j = 0; j < h; j++ )
@@ -334,7 +334,7 @@ NetGraph_DrawHatches
*/
static void NetGraph_DrawHatches( int x, int y )
{
int ystep = (int)( 10.0f / net_scale.value );
int ystep = (int)( 10.0f / net_scale->value );
byte colorminor[4] = { 0, 63, 63, 200 };
byte color[4] = { 0, 200, 0, 255 };
wrect_t hatch = { x, 4, y, 1 };
@@ -342,9 +342,9 @@ static void NetGraph_DrawHatches( int x, int y )
ystep = Q_max( ystep, 1 );
for( starty = hatch.top; hatch.top > 0 && ((starty - hatch.top) * net_scale.value < (maxmsgbytes + 50)); hatch.top -= ystep )
for( starty = hatch.top; hatch.top > 0 && ((starty - hatch.top) * net_scale->value < (maxmsgbytes + 50)); hatch.top -= ystep )
{
if(!((int)((starty - hatch.top) * net_scale.value ) % 50 ))
if(!((int)((starty - hatch.top) * net_scale->value ) % 50 ))
{
NetGraph_DrawRect( &hatch, color );
}
@@ -370,14 +370,14 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
int pty = Q_max( rect.top + rect.bottom - NETGRAPH_LERP_HEIGHT - 3, 1 );
int out, i = ( cls.netchan.outgoing_sequence - 1 ) & NET_TIMINGS_MASK;
int j = cls.netchan.incoming_sequence & NET_TIMINGS_MASK;
int last_y = y - net_graphheight.value;
int last_y = y - net_graphheight->value;
if( count > 0 )
{
avg = avg / (float)( count - ( host.frametime * FRAMERATE_AVG_FRAC ));
if( cl_updaterate.value > 0.0f )
avg -= 1000.0f / cl_updaterate.value;
if( cl_updaterate->value > 0.0f )
avg -= 1000.0f / cl_updaterate->value;
// can't be below zero
avg = Q_max( 0.0f, avg );
@@ -387,11 +387,11 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
// move rolling average
framerate = FRAMERATE_AVG_FRAC * host.frametime + ( 1.0f - FRAMERATE_AVG_FRAC ) * framerate;
CL_SetFontRendermode( font );
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
if( framerate > 0.0f )
{
y -= net_graphheight.value;
y -= net_graphheight->value;
CL_DrawStringf( font, x, y, colors, FONT_DRAW_NORENDERMODE, "%.1f fps" , 1.0f / framerate);
@@ -422,9 +422,9 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
}
if( graphtype < 3 )
CL_DrawStringf( font, ptx, pty, colors, FONT_DRAW_NORENDERMODE, "%i/s", (int)cl_cmdrate.value );
CL_DrawStringf( font, ptx, pty, colors, FONT_DRAW_NORENDERMODE, "%i/s", (int)cl_cmdrate->value );
CL_DrawStringf( font, ptx, last_y, colors, FONT_DRAW_NORENDERMODE, "%i/s" , (int)cl_updaterate.value );
CL_DrawStringf( font, ptx, last_y, colors, FONT_DRAW_NORENDERMODE, "%i/s" , (int)cl_updaterate->value );
}
/*
@@ -435,12 +435,12 @@ NetGraph_DrawDataSegment
*/
static int NetGraph_DrawDataSegment( wrect_t *fill, int bytes, byte r, byte g, byte b, byte a )
{
float h = bytes / net_scale.value;
float h = bytes / net_scale->value;
byte colors[4] = { r, g, b, a };
fill->top -= (int)h;
if( net_graphsolid.value )
if( net_graphsolid->value )
fill->bottom = (int)h;
else fill->bottom = 1;
@@ -498,7 +498,7 @@ NetGraph_DrawDataUsage
static void NetGraph_DrawDataUsage( int x, int y, int w, int graphtype )
{
int a, i, h, lastvalidh = 0, ping;
int pingheight = net_graphheight.value - NETGRAPH_LERP_HEIGHT - 2;
int pingheight = net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2;
wrect_t fill = { 0 };
byte color[4];
@@ -554,7 +554,7 @@ static void NetGraph_DrawDataUsage( int x, int y, int w, int graphtype )
continue;
color[0] = color[1] = color[2] = color[3] = 255;
fill.top = y - net_graphheight.value - 1;
fill.top = y - net_graphheight->value - 1;
fill.bottom = 1;
if( NetGraph_AtEdge( a, w ))
@@ -589,7 +589,7 @@ static void NetGraph_DrawDataUsage( int x, int y, int w, int graphtype )
if( !NetGraph_DrawDataSegment( &fill, netstat_graph[i].voicebytes, 255, 255, 255, 255 ))
continue;
fill.top = y - net_graphheight.value - 1;
fill.top = y - net_graphheight->value - 1;
fill.bottom = 1;
fill.top -= 2;
@@ -598,7 +598,7 @@ static void NetGraph_DrawDataUsage( int x, int y, int w, int graphtype )
}
if( graphtype >= 2 )
NetGraph_DrawHatches( x, y - net_graphheight.value - 1 );
NetGraph_DrawHatches( x, y - net_graphheight->value - 1 );
}
/*
@@ -613,12 +613,12 @@ static void NetGraph_GetScreenPos( wrect_t *rect, int *w, int *x, int *y )
rect->right = refState.width;
rect->bottom = refState.height;
*w = Q_min( NET_TIMINGS, net_graphwidth.value );
*w = Q_min( NET_TIMINGS, net_graphwidth->value );
if( rect->right < *w + 10 )
*w = rect->right - 10;
// detect x and y position
switch( (int)net_graphpos.value )
switch( (int)net_graphpos->value )
{
case 1: // right sided
*x = rect->left + rect->right - 5 - *w;
@@ -661,16 +661,16 @@ void SCR_DrawNetGraph( void )
{
graphtype = 2;
}
else if( net_graph.value != 0.0f )
else if( net_graph->value != 0.0f )
{
graphtype = (int)net_graph.value;
graphtype = (int)net_graph->value;
}
else
{
return;
}
if( net_scale.value <= 0 )
if( net_scale->value <= 0 )
Cvar_SetValue( "net_scale", 0.1f );
NetGraph_GetScreenPos( &rect, &w, &x, &y );
@@ -697,12 +697,12 @@ void SCR_DrawNetGraph( void )
void CL_InitNetgraph( void )
{
Cvar_RegisterVariable( &net_graph );
Cvar_RegisterVariable( &net_graphpos );
Cvar_RegisterVariable( &net_scale );
Cvar_RegisterVariable( &net_graphwidth );
Cvar_RegisterVariable( &net_graphheight );
Cvar_RegisterVariable( &net_graphsolid );
net_graph = Cvar_Get( "net_graph", "0", FCVAR_ARCHIVE, "draw network usage graph" );
net_graphpos = Cvar_Get( "net_graphpos", "1", FCVAR_ARCHIVE, "network usage graph position" );
net_scale = Cvar_Get( "net_scale", "5", FCVAR_ARCHIVE, "network usage graph scale level" );
net_graphwidth = Cvar_Get( "net_graphwidth", "192", FCVAR_ARCHIVE, "network usage graph width" );
net_graphheight = Cvar_Get( "net_graphheight", "64", FCVAR_ARCHIVE, "network usage graph height" );
net_graphsolid = Cvar_Get( "net_graphsolid", "1", FCVAR_ARCHIVE, "fill segments in network usage graph" );
packet_loss = packet_choke = 0.0;
NetGraph_InitColors();

File diff suppressed because it is too large Load Diff

View File

@@ -1,665 +0,0 @@
/*
cl_parse.c - parse a message received from the server
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"
/*
==================
CL_ParseStaticEntity
static client entity
==================
*/
static void CL_LegacyParseStaticEntity( sizebuf_t *msg )
{
int i;
entity_state_t state;
cl_entity_t *ent;
memset( &state, 0, sizeof( state ));
state.modelindex = MSG_ReadShort( msg );
state.sequence = MSG_ReadByte( msg );
state.frame = MSG_ReadByte( msg );
state.colormap = MSG_ReadWord( msg );
state.skin = MSG_ReadByte( msg );
for( i = 0; i < 3; i++ )
{
state.origin[i] = MSG_ReadCoord( msg );
state.angles[i] = MSG_ReadBitAngle( msg, 16 );
}
state.rendermode = MSG_ReadByte( msg );
if( state.rendermode != kRenderNormal )
{
state.renderamt = MSG_ReadByte( msg );
state.rendercolor.r = MSG_ReadByte( msg );
state.rendercolor.g = MSG_ReadByte( msg );
state.rendercolor.b = MSG_ReadByte( msg );
state.renderfx = MSG_ReadByte( msg );
}
i = clgame.numStatics;
if( i >= MAX_STATIC_ENTITIES )
{
Con_Printf( S_ERROR "MAX_STATIC_ENTITIES limit exceeded!\n" );
return;
}
ent = &clgame.static_entities[i];
clgame.numStatics++;
// all states are same
ent->baseline = ent->curstate = ent->prevstate = state;
ent->index = 0; // static entities doesn't has the numbers
// statics may be respawned in game e.g. for demo recording
if( cls.state == ca_connected || cls.state == ca_validate )
ent->trivial_accept = INVALID_HANDLE;
// setup the new static entity
VectorCopy( ent->curstate.origin, ent->origin );
VectorCopy( ent->curstate.angles, ent->angles );
ent->model = CL_ModelHandle( state.modelindex );
ent->curstate.framerate = 1.0f;
CL_ResetLatchedVars( ent, true );
if( ent->curstate.rendermode == kRenderNormal && ent->model != NULL )
{
// auto 'solid' faces
if( FBitSet( ent->model->flags, MODEL_TRANSPARENT ) && Host_IsQuakeCompatible( ))
{
ent->curstate.rendermode = kRenderTransAlpha;
ent->curstate.renderamt = 255;
}
}
R_AddEfrags( ent ); // add link
}
static void CL_LegacyParseSoundPacket( sizebuf_t *msg, qboolean is_ambient )
{
vec3_t pos;
int chan, sound;
float volume, attn;
int flags, pitch, entnum;
sound_t handle = 0;
flags = MSG_ReadWord( msg );
if( flags & SND_LEGACY_LARGE_INDEX )
{
sound = MSG_ReadWord( msg );
flags &= ~SND_LEGACY_LARGE_INDEX;
}
else
sound = MSG_ReadByte( msg );
chan = MSG_ReadByte( msg );
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;
if( FBitSet( flags, SND_PITCH ))
pitch = MSG_ReadByte( msg );
else pitch = PITCH_NORM;
// entity reletive
entnum = MSG_ReadWord( msg );
// positioned in space
MSG_ReadVec3Coord( msg, pos );
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
if( !cl.audio_prepped )
return; // too early
// g-cont. sound and ambient sound have only difference with channel
if( is_ambient )
{
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
}
else
{
S_StartSound( pos, entnum, chan, handle, volume, attn, pitch, flags );
}
}
/*
================
CL_PrecacheSound
prceache sound from server
================
*/
static void CL_LegacyPrecacheSound( sizebuf_t *msg )
{
int soundIndex;
soundIndex = MSG_ReadUBitLong( msg, MAX_SOUND_BITS );
if( soundIndex < 0 || soundIndex >= MAX_SOUNDS )
Host_Error( "%s: bad soundindex %i\n", __func__, soundIndex );
Q_strncpy( cl.sound_precache[soundIndex], MSG_ReadString( msg ), sizeof( cl.sound_precache[0] ));
// when we loading map all resources is precached sequentially
//if( !cl.audio_prepped ) return;
cl.sound_index[soundIndex] = S_RegisterSound( cl.sound_precache[soundIndex] );
}
static void CL_LegacyPrecacheModel( sizebuf_t *msg )
{
int modelIndex;
string model;
modelIndex = MSG_ReadUBitLong( msg, MAX_LEGACY_MODEL_BITS );
if( modelIndex < 0 || modelIndex >= MAX_MODELS )
Host_Error( "%s: bad modelindex %i\n", __func__, modelIndex );
Q_strncpy( model, MSG_ReadString( msg ), sizeof( model ));
//Q_strncpy( cl.model_precache[modelIndex], BF_ReadString( msg ), sizeof( cl.model_precache[0] ));
// when we loading map all resources is precached sequentially
//if( !cl.video_prepped ) return;
if( modelIndex == 1 && !cl.worldmodel )
{
CL_ClearWorld ();
cl.models[modelIndex] = cl.worldmodel = Mod_LoadWorld( model, true );
return;
}
//Mod_RegisterModel( cl.model_precache[modelIndex], modelIndex );
cl.models[modelIndex] = Mod_ForName( model, false, false );
cl.nummodels = Q_max( cl.nummodels, modelIndex );
}
static void CL_LegacyPrecacheEvent( sizebuf_t *msg )
{
int eventIndex;
eventIndex = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
if( eventIndex < 0 || eventIndex >= MAX_EVENTS )
Host_Error( "%s: bad eventindex %i\n", __func__, eventIndex );
Q_strncpy( cl.event_precache[eventIndex], MSG_ReadString( msg ), sizeof( cl.event_precache[0] ));
// can be set now
CL_SetEventIndex( cl.event_precache[eventIndex], eventIndex );
}
#if XASH_LOW_MEMORY == 0
#define MAX_LEGACY_RESOURCES 2048
#elif XASH_LOW_MEMORY == 2
#define MAX_LEGACY_RESOURCES 1
#elif XASH_LOW_MEMORY == 1
#define MAX_LEGACY_RESOURCES 512
#endif
/*
==============
CL_ParseResourceList
==============
*/
static void CL_LegacyParseResourceList( sizebuf_t *msg )
{
int i = 0;
static struct
{
int rescount;
int restype[MAX_LEGACY_RESOURCES];
char resnames[MAX_LEGACY_RESOURCES][MAX_QPATH];
} reslist;
memset( &reslist, 0, sizeof( reslist ));
reslist.rescount = MSG_ReadWord( msg ) - 1;
if( reslist.rescount > MAX_LEGACY_RESOURCES )
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] ));
}
if( cls.demoplayback )
return;
if( !cl_allow_download.value )
{
Con_DPrintf( "Refusing new resource, cl_allow_download set to 0\n" );
reslist.rescount = 0;
}
if( cls.state == ca_active && !cl_download_ingame.value )
{
Con_DPrintf( "Refusing new resource, cl_download_ingame set to 0\n" );
reslist.rescount = 0;
}
HTTP_ResetProcessState();
host.downloadcount = 0;
for( i = 0; i < reslist.rescount; i++ )
{
char soundpath[MAX_VA_STRING];
const char *path;
if( reslist.restype[i] == t_sound )
{
Q_snprintf( soundpath, sizeof( soundpath ), DEFAULT_SOUNDPATH "%s", reslist.resnames[i] );
path = soundpath;
}
else path = reslist.resnames[i];
if( FS_FileExists( path, false ))
continue; // already exists
host.downloadcount++;
HTTP_AddDownload( path, -1, true );
}
if( !host.downloadcount )
{
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_WriteString( &cls.netchan.message, "continueloading" );
}
}
/*
=====================
CL_ParseLegacyServerMessage
dispatch messages
=====================
*/
void CL_ParseLegacyServerMessage( sizebuf_t *msg )
{
size_t bufStart, playerbytes;
int cmd, param1, param2;
int old_background;
const char *s;
// parse the message
while( 1 )
{
if( MSG_CheckOverflow( msg ))
{
Host_Error( "%s: overflow!\n", __func__ );
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 );
// other commands
switch( cmd )
{
case svc_bad:
Host_Error( "svc_bad\n" );
break;
case svc_nop:
// this does nothing
break;
case svc_disconnect:
CL_Drop ();
Host_AbortCurrentFrame ();
break;
case svc_legacy_event:
CL_ParseEvent( msg );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_legacy_changing:
old_background = cl.background;
if( MSG_ReadOneBit( msg ))
{
int maxclients = cl.maxclients;
// we can only changelevel in singleplayer
// and singleplayer always runs in current protocol
// cls.changelevel = true;
S_StopAllSounds( true );
Con_Printf( "Server changing, reconnecting\n" );
if( cls.demoplayback )
{
SCR_BeginLoadingPlaque( cl.background );
cls.changedemo = true;
}
CL_ClearState( );
// a1ba: need to restore cl.maxclients because engine chooses
// frame backups count depending on this value
// In general, it's incorrect to call CL_InitEdicts right after
// CL_ClearState because of this bug. Some time later this logic
// should be re-done.
CL_InitEdicts( maxclients ); // re-arrange edicts
}
else Con_Printf( "Server disconnected, reconnecting\n" );
if( cls.demoplayback )
{
cl.background = (cls.demonum != -1) ? true : false;
cls.state = ca_connected;
}
else
{
// g-cont. local client skip the challenge
if( SV_Active( ))
cls.state = ca_disconnected;
else cls.state = ca_connecting;
cl.background = old_background;
cls.connect_time = MAX_HEARTBEAT;
cls.connect_retry = 0;
}
break;
case svc_setview:
CL_ParseViewEntity( msg );
break;
case svc_sound:
CL_LegacyParseSoundPacket( msg, false );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_legacy_ambientsound:
CL_LegacyParseSoundPacket( msg, true );
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_time:
CL_ParseServerTime( msg );
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_serverdata:
Cbuf_Execute(); // make sure any stuffed commands are done
CL_ParseServerData( msg, true );
break;
case svc_lightstyle:
CL_ParseLightStyle( msg );
break;
case svc_updateuserinfo:
CL_UpdateUserinfo( msg, true );
break;
case svc_deltatable:
Delta_ParseTableField( msg );
break;
case svc_clientdata:
CL_ParseClientData( msg );
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_resource:
CL_ParseResource( msg );
break;
case svc_pings:
CL_UpdateUserPings( msg );
break;
case svc_particle:
CL_ParseParticles( msg );
break;
case svc_restoresound:
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 );
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
break;
case svc_spawnbaseline:
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 );
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 );
break;
case svc_packetentities:
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 );
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
break;
case svc_legacy_chokecount:
{
int i, j;
i = MSG_ReadByte( msg );
j = cls.netchan.incoming_acknowledged - 1;
for( ; i > 0 && j > cls.netchan.outgoing_sequence - CL_UPDATE_BACKUP; j-- )
{
if( cl.frames[j & CL_UPDATE_MASK].receivedtime != -3.0 )
{
cl.frames[j & CL_UPDATE_MASK].choked = true;
cl.frames[j & CL_UPDATE_MASK].receivedtime = -2.0;
i--;
}
}
break;
}
//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:
CL_LegacyParseResourceList( msg );
break;
case svc_deltamovevars:
CL_ParseMovevars( 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_director:
CL_ParseDirector( msg );
break;
case svc_resourcelocation:
CL_ParseResLocation( msg );
break;
case svc_querycvarvalue:
CL_ParseCvarValue( msg, false, PROTO_LEGACY );
break;
case svc_querycvarvalue2:
CL_ParseCvarValue( msg, true, PROTO_LEGACY );
break;
default:
CL_ParseUserMessage( msg, cmd );
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
break;
}
}
}
void CL_LegacyPrecache_f( void )
{
int spawncount, i;
model_t *mod;
if( !cls.legacymode )
return;
spawncount = Q_atoi( Cmd_Argv( 1 ));
Con_Printf( "Setting up renderer...\n" );
// load tempent sprites (glowshell, muzzleflashes etc)
CL_LoadClientSprites ();
// invalidate all decal indexes
memset( cl.decal_index, 0, sizeof( cl.decal_index ));
cl.video_prepped = true;
cl.audio_prepped = true;
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 ();
CL_SetupOverviewParams();
// release unused SpriteTextures
for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ )
{
if( mod->needload == NL_UNREFERENCED && COM_CheckString( mod->name ))
Mod_FreeModel( mod );
}
// Mod_FreeUnused ();
if( host_developer.value <= DEV_NONE )
Con_ClearNotify(); // clear any lines of console text
// done with all resources, issue prespawn command.
// 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;
}
qboolean CL_LegacyMode( void )
{
return cls.legacymode == PROTO_LEGACY;
}

View File

@@ -54,6 +54,31 @@ void GAME_EXPORT CL_PopPMStates( void )
clgame.pushed = false;
}
/*
=============
CL_PushTraceBounds
=============
*/
void GAME_EXPORT CL_PushTraceBounds( int hullnum, const float *mins, const float *maxs )
{
hullnum = bound( 0, hullnum, 3 );
VectorCopy( mins, clgame.pmove->player_mins[hullnum] );
VectorCopy( maxs, clgame.pmove->player_maxs[hullnum] );
}
/*
=============
CL_PopTraceBounds
=============
*/
void GAME_EXPORT CL_PopTraceBounds( void )
{
memcpy( clgame.pmove->player_mins, host.player_mins, sizeof( host.player_mins ));
memcpy( clgame.pmove->player_maxs, host.player_maxs, sizeof( host.player_maxs ));
}
/*
===============
CL_IsPredicted
@@ -61,7 +86,7 @@ CL_IsPredicted
*/
qboolean CL_IsPredicted( void )
{
if( cl_nopred.value || cl.intermission )
if( cl_nopred->value || cl.intermission )
return false;
// never predict the quake demos
@@ -158,7 +183,7 @@ void CL_SetIdealPitch( void )
}
if( steps < 2 ) return;
cl.local.idealpitch = -dir * cl_idealpitchscale.value;
cl.local.idealpitch = -dir * cl_idealpitchscale->value;
}
/*
@@ -209,7 +234,7 @@ void CL_CheckPredictionError( void )
// save the prediction error for interpolation
if( dist > MAX_PREDICTION_ERROR )
{
if( cl_showerror.value && host_developer.value )
if( cl_showerror->value && host_developer.value )
Con_NPrintf( 10 + ( ++pos & 3 ), "^3player teleported:^7 %.3f units\n", dist );
// a teleport or something or gamepaused
@@ -217,7 +242,7 @@ void CL_CheckPredictionError( void )
}
else
{
if( cl_showerror.value && dist > MIN_PREDICTION_EPSILON && host_developer.value )
if( cl_showerror->value && dist > MIN_PREDICTION_EPSILON && host_developer.value )
Con_NPrintf( 10 + ( ++pos & 3 ), "^1prediction error:^7 %.3f units\n", dist );
VectorCopy( cl.frames[cmd].playerstate[cl.playernum].origin, cl.local.predicted_origins[frame] );
@@ -228,7 +253,7 @@ void CL_CheckPredictionError( void )
// GoldSrc checks for singleplayer
// we would check for local server
if( dist > MIN_CORRECTION_DISTANCE && !SV_Active() )
cls.correction_time = cl_smoothtime.value;
cls.correction_time = cl_smoothtime->value;
}
}
@@ -392,7 +417,7 @@ CL_AddLinksToPmove
collect solid entities
====================
*/
static void CL_AddLinksToPmove( frame_t *frame )
void CL_AddLinksToPmove( frame_t *frame )
{
entity_state_t *state;
model_t *model;
@@ -508,7 +533,7 @@ void GAME_EXPORT CL_SetSolidPlayers( int playernum )
physent_t *pe;
int i;
if( !cl_solid_players.value )
if( !cl_solid_players->value )
return;
for( i = 0; i < MAX_CLIENTS; i++ )
@@ -662,6 +687,11 @@ cl_entity_t *CL_GetWaterEntity( const float *rgflPos )
return CL_GetEntityByIndex( entnum );
}
int GAME_EXPORT CL_TestLine( const vec3_t start, const vec3_t end, int flags )
{
return PM_TestLineExt( clgame.pmove, clgame.pmove->physents, clgame.pmove->numphysent, start, end, flags );
}
static int GAME_EXPORT pfnTestPlayerPosition( float *pos, pmtrace_t *ptrace )
{
return PM_TestPlayerPosition( clgame.pmove, pos, ptrace, NULL );
@@ -794,16 +824,6 @@ static void CL_SetupPMove( playermove_t *pmove, const local_state_t *from, const
cd = &from->client;
pmove->player_index = ps->number - 1;
// a1ba: workaround bug where the server refuse to send our local player in delta
// cl.playernum, in theory, must be equal to our local player index anyway
//
// this might not be a real solution, since everything else will be bogus
// but we need to properly run prediction and avoid potential memory
// corruption
if( pmove->player_index < 0 )
pmove->player_index = bound( 0, cl.playernum, cl.maxclients - 1 );
pmove->multiplayer = (cl.maxclients > 1);
pmove->runfuncs = runfuncs;
pmove->time = time * 1000.0f;
@@ -853,10 +873,10 @@ 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 )
const void CL_FinishPMove( const playermove_t *pmove, local_state_t *to )
{
entity_state_t *ps;
clientdata_t *cd;
@@ -909,7 +929,7 @@ CL_RunUsercmd
Runs prediction code for user cmd
=================
*/
static void CL_RunUsercmd( local_state_t *from, local_state_t *to, usercmd_t *u, qboolean runfuncs, double *time, unsigned int random_seed )
void CL_RunUsercmd( local_state_t *from, local_state_t *to, usercmd_t *u, qboolean runfuncs, double *time, unsigned int random_seed )
{
usercmd_t cmd;
@@ -1085,7 +1105,7 @@ void CL_PredictMovement( qboolean repredicting )
cl.local.onground = frame->playerstate[cl.playernum].onground;
else cl.local.onground = -1;
if( !repredicting || !cl_lw.value )
if( !repredicting || !CVAR_TO_BOOL( cl_lw ))
cl.local.viewmodel = to->client.viewmodel;
cl.local.repredicting = false;
cl.local.moving = false;
@@ -1117,7 +1137,7 @@ void CL_PredictMovement( qboolean repredicting )
cl.local.waterlevel = to->client.waterlevel;
cl.local.usehull = to->playerstate.usehull;
if( !repredicting || !cl_lw.value )
if( !repredicting || !CVAR_TO_BOOL( cl_lw ))
cl.local.viewmodel = to->client.viewmodel;
if( FBitSet( to->client.flags, FL_ONGROUND ))
@@ -1147,7 +1167,7 @@ void CL_PredictMovement( qboolean repredicting )
cl.local.moving = false;
}
if( cls.correction_time > 0 && !cl_nosmooth.value && cl_smoothtime.value )
if( cls.correction_time > 0 && !cl_nosmooth->value && cl_smoothtime->value )
{
vec3_t delta;
float frac;
@@ -1157,14 +1177,14 @@ void CL_PredictMovement( qboolean repredicting )
cls.correction_time -= host.frametime;
// Make sure smoothtime is postive
if( cl_smoothtime.value <= 0.0f )
Cvar_DirectSet( &cl_smoothtime, "0.1" );
if( cl_smoothtime->value <= 0.0f )
Cvar_DirectSet( cl_smoothtime, "0.1" );
// Clamp from 0 to cl_smoothtime.value
cls.correction_time = bound( 0.0, cls.correction_time, cl_smoothtime.value );
cls.correction_time = bound( 0.0, cls.correction_time, cl_smoothtime->value );
// Compute backward interpolation fraction along full correction
frac = 1.0f - cls.correction_time / cl_smoothtime.value;
frac = 1.0f - cls.correction_time / cl_smoothtime->value;
// Determine how much error we still have to make up for
VectorSubtract( cl.simorg, cl.local.lastorigin, delta );

View File

@@ -211,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();
@@ -232,10 +232,10 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
// loading user settings
CSCR_LoadDefaultCVars( "user.scr" );
if( r_decals.value > mp_decals.value )
Cvar_DirectSet( &r_decals, mp_decals.string );
if( r_decals->value > mp_decals.value )
Cvar_SetValue( "r_decals", mp_decals.value );
}
else Cvar_DirectSet( &r_decals, NULL );
else Cvar_Reset( "r_decals" );
if( cl.background ) // tell the game parts about background state
Cvar_FullSet( "cl_background", "1", FCVAR_READ_ONLY );
@@ -258,7 +258,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
Q_strncpy( gameui.globals->maptitle, clgame.maptitle, sizeof( gameui.globals->maptitle ));
if( !cls.changelevel && !cls.changedemo )
CL_InitEdicts( cl.maxclients ); // re-arrange edicts
CL_InitEdicts (); // re-arrange edicts
// Quake just have a large packet of initialization data
for( i = 1; i < MAX_MODELS; i++ )
@@ -302,9 +302,9 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
else Cvar_Set( "cl_levelshot_name", va( "levelshots/%s_%s", clgame.mapname, refState.wideScreen ? "16x9" : "4x3" ));
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
if(( cl_allow_levelshots.value && !cls.changelevel ) || cl.background )
if(( cl_allow_levelshots->value && !cls.changelevel ) || cl.background )
{
if( !FS_FileExists( va( "%s.bmp", cl_levelshot_name.string ), true ))
if( !FS_FileExists( va( "%s.bmp", cl_levelshot_name->string ), true ))
Cvar_Set( "cl_levelshot_name", "*black" ); // render a black screen
cls.scrshot_request = scrshot_plaque; // request levelshot even if exist (check filetime)
}
@@ -414,7 +414,7 @@ If an entities model or origin changes from frame to frame, it must be
relinked. Other attributes can change without relinking.
==================
*/
static void CL_ParseQuakeEntityData( sizebuf_t *msg, int bits )
void CL_ParseQuakeEntityData( sizebuf_t *msg, int bits )
{
int i, newnum, pack;
qboolean forcelink;
@@ -565,7 +565,7 @@ CL_ParseQuakeParticles
==================
*/
static void CL_ParseQuakeParticle( sizebuf_t *msg )
void CL_ParseQuakeParticle( sizebuf_t *msg )
{
int count, color;
vec3_t org, dir;
@@ -587,7 +587,7 @@ CL_ParseQuakeStaticSound
===================
*/
static void CL_ParseQuakeStaticSound( sizebuf_t *msg )
void CL_ParseQuakeStaticSound( sizebuf_t *msg )
{
int sound_num;
float vol, attn;
@@ -620,11 +620,11 @@ static void CL_ParseQuakeDamage( sizebuf_t *msg )
/*
===================
CL_ParseStaticEntity
CL_ParseQuakeStaticEntity
===================
*/
static void CL_ParseStaticEntity( sizebuf_t *msg )
static void CL_ParseQuakeStaticEntity( sizebuf_t *msg )
{
entity_state_t state;
cl_entity_t *ent;
@@ -646,7 +646,7 @@ static void CL_ParseStaticEntity( 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;
}
@@ -694,13 +694,17 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
cl_entity_t *ent;
int newnum;
memset( &state, 0, sizeof( state ));
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" );
ent = CL_EDICT_NUM( newnum );
memset( &ent->prevstate, 0, sizeof( ent->prevstate ));
ent->index = newnum;
// parse baseline
memset( &state, 0, sizeof( state ));
state.modelindex = MSG_ReadByte( msg );
state.frame = MSG_ReadByte( msg );
state.colormap = MSG_ReadByte( msg );
@@ -711,10 +715,8 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
state.angles[1] = MSG_ReadAngle( msg );
state.origin[2] = MSG_ReadCoord( msg );
state.angles[2] = MSG_ReadAngle( msg );
ent = CL_EDICT_NUM( newnum );
ent->index = newnum;
ent->player = CL_IsPlayerIndex( newnum );
memcpy( &ent->baseline, &state, sizeof( entity_state_t ));
memcpy( &ent->prevstate, &state, sizeof( entity_state_t ));
}
@@ -778,7 +780,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 );
}
/*
@@ -816,7 +818,7 @@ CL_QuakeStuffText
==================
*/
static void CL_QuakeStuffText( const char *text )
void CL_QuakeStuffText( const char *text )
{
Q_strncat( cmd_buf, text, sizeof( cmd_buf ));
@@ -831,7 +833,7 @@ CL_QuakeExecStuff
==================
*/
static void CL_QuakeExecStuff( void )
void CL_QuakeExecStuff( void )
{
char *text = cmd_buf;
char token[256];
@@ -844,7 +846,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' )
@@ -886,21 +888,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;
}
@@ -1005,7 +1024,7 @@ void CL_ParseQuakeMessage( sizebuf_t *msg )
CL_ParseQuakeDamage( msg );
break;
case svc_spawnstatic:
CL_ParseStaticEntity( msg );
CL_ParseQuakeStaticEntity( msg );
break;
case svc_spawnbinary:
// never used in Quake
@@ -1091,11 +1110,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

@@ -41,24 +41,11 @@ CL_CmpStudioTextures
return true if equal
====================
*/
static qboolean CL_CmpStudioTextures( int numtexs, mstudiotexture_t *p1, remap_info_t *remap )
qboolean CL_CmpStudioTextures( int numtexs, mstudiotexture_t *p1, mstudiotexture_t *p2 )
{
int i;
mstudiotexture_t *p2;
if( !p1 ) // no textures
return false;
if( !remap ) // current model has no remap
return false;
if( !remap->textures ) // shouldn't happen, just in case
return false;
if( numtexs != remap->numtextures ) // amount of textures differs, it's a different model
return false;
p2 = remap->ptexture;
if( !p1 || !p2 ) return false;
for( i = 0; i < numtexs; i++, p1++, p2++ )
{
@@ -78,7 +65,7 @@ CL_CreateRawTextureFromPixels
Convert texture_t struct into mstudiotexture_t prototype
====================
*/
static byte *CL_CreateRawTextureFromPixels( texture_t *tx, size_t *size, int topcolor, int bottomcolor )
byte *CL_CreateRawTextureFromPixels( texture_t *tx, size_t *size, int topcolor, int bottomcolor )
{
static mstudiotexture_t pin;
byte *pal;
@@ -111,7 +98,7 @@ CL_DuplicateTexture
Dupliacte texture with remap pixels
====================
*/
static void CL_DuplicateTexture( cl_entity_t *entity, model_t *model, mstudiotexture_t *ptexture, int topcolor, int bottomcolor )
void CL_DuplicateTexture( cl_entity_t *entity, model_t *model, mstudiotexture_t *ptexture, int topcolor, int bottomcolor )
{
const char *name;
texture_t *tx = NULL;
@@ -154,7 +141,7 @@ CL_UpdateStudioTexture
Update texture top and bottom colors
====================
*/
static void CL_UpdateStudioTexture( cl_entity_t *entity, mstudiotexture_t *ptexture, int topcolor, int bottomcolor )
void CL_UpdateStudioTexture( cl_entity_t *entity, mstudiotexture_t *ptexture, int topcolor, int bottomcolor )
{
rgbdata_t *pic;
texture_t *tx = NULL;
@@ -215,7 +202,7 @@ CL_UpdateAliasTexture
Update texture top and bottom colors
====================
*/
static void CL_UpdateAliasTexture( cl_entity_t *entity, unsigned short *texture, int skinnum, int topcolor, int bottomcolor )
void CL_UpdateAliasTexture( cl_entity_t *entity, unsigned short *texture, int skinnum, int topcolor, int bottomcolor )
{
char texname[MAX_QPATH];
rgbdata_t skin, *pic;
@@ -247,68 +234,6 @@ static void CL_UpdateAliasTexture( cl_entity_t *entity, unsigned short *texture,
ref.dllFuncs.GL_ProcessTexture( *texture, -1.0f, topcolor, bottomcolor );
}
/*
====================
CL_FreeRemapInfo
Release remap info per entity
====================
*/
static void CL_FreeRemapInfo( remap_info_t *info )
{
int i;
Assert( info != NULL );
// release all colormap texture copies
for( i = 0; i < info->numtextures; i++ )
{
if( info->ptexture != NULL )
{
if( FBitSet( info->ptexture[i].flags, STUDIO_NF_COLORMAP ))
ref.dllFuncs.GL_FreeTexture( info->ptexture[i].index );
}
if( info->textures[i] != 0 )
ref.dllFuncs.GL_FreeTexture( info->textures[i] );
}
Mem_Free( info ); // release struct
}
/*
====================
CL_UpdateRemapInfo
Update all remaps per entity
====================
*/
static void CL_UpdateRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor )
{
remap_info_t *info;
int i;
i = ( entity == &clgame.viewent ) ? clgame.maxEntities : entity->curstate.number;
info = clgame.remap_info[i];
if( !info ) return; // no remap info
if( info->topcolor == topcolor && info->bottomcolor == bottomcolor )
return; // values is valid
for( i = 0; i < info->numtextures; i++ )
{
if( info->ptexture != NULL )
{
if( FBitSet( info->ptexture[i].flags, STUDIO_NF_COLORMAP ))
CL_UpdateStudioTexture( entity, &info->ptexture[i], topcolor, bottomcolor );
}
else CL_UpdateAliasTexture( entity, &info->textures[i], i, topcolor, bottomcolor );
}
info->topcolor = topcolor;
info->bottomcolor = bottomcolor;
}
/*
====================
CL_AllocRemapInfo
@@ -317,7 +242,7 @@ Allocate new remap info per entity
and make copy of remap textures
====================
*/
static void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor, int bottomcolor )
void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor, int bottomcolor )
{
remap_info_t *info;
studiohdr_t *phdr;
@@ -357,9 +282,10 @@ static void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor
if( !phdr ) return; // bad model?
src = (mstudiotexture_t *)(((byte *)phdr) + phdr->textureindex);
dst = (clgame.remap_info[i] ? clgame.remap_info[i]->ptexture : NULL);
// NOTE: we must copy all the structures 'mstudiotexture_t' for easy access when model is rendering
if( !CL_CmpStudioTextures( phdr->numtextures, src, clgame.remap_info[i] ) || clgame.remap_info[i]->model != model )
if( !CL_CmpStudioTextures( phdr->numtextures, src, dst ) || clgame.remap_info[i]->model != model )
{
// this code catches studiomodel change with another studiomodel with remap textures
// e.g. playermodel 'barney' with playermodel 'gordon'
@@ -424,6 +350,68 @@ static void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor
info->model = model;
}
/*
====================
CL_UpdateRemapInfo
Update all remaps per entity
====================
*/
void CL_UpdateRemapInfo( cl_entity_t *entity, int topcolor, int bottomcolor )
{
remap_info_t *info;
int i;
i = ( entity == &clgame.viewent ) ? clgame.maxEntities : entity->curstate.number;
info = clgame.remap_info[i];
if( !info ) return; // no remap info
if( info->topcolor == topcolor && info->bottomcolor == bottomcolor )
return; // values is valid
for( i = 0; i < info->numtextures; i++ )
{
if( info->ptexture != NULL )
{
if( FBitSet( info->ptexture[i].flags, STUDIO_NF_COLORMAP ))
CL_UpdateStudioTexture( entity, &info->ptexture[i], topcolor, bottomcolor );
}
else CL_UpdateAliasTexture( entity, &info->textures[i], i, topcolor, bottomcolor );
}
info->topcolor = topcolor;
info->bottomcolor = bottomcolor;
}
/*
====================
CL_FreeRemapInfo
Release remap info per entity
====================
*/
void CL_FreeRemapInfo( remap_info_t *info )
{
int i;
Assert( info != NULL );
// release all colormap texture copies
for( i = 0; i < info->numtextures; i++ )
{
if( info->ptexture != NULL )
{
if( FBitSet( info->ptexture[i].flags, STUDIO_NF_COLORMAP ))
ref.dllFuncs.GL_FreeTexture( info->ptexture[i].index );
}
if( info->textures[i] != 0 )
ref.dllFuncs.GL_FreeTexture( info->textures[i] );
}
Mem_Free( info ); // release struct
}
/*
====================
CL_ClearAllRemaps
@@ -446,21 +434,3 @@ void CL_ClearAllRemaps( void )
}
clgame.remap_info = NULL;
}
/*
=============
CL_EntitySetRemapColors
=============
*/
qboolean CL_EntitySetRemapColors( cl_entity_t *e, model_t *mod, int top, int bottom )
{
CL_AllocRemapInfo( e, mod, top, bottom );
if( CL_GetRemapInfoForEntity( e ))
{
CL_UpdateRemapInfo( e, top, bottom );
return true;
}
return false;
}

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 )
@@ -126,7 +126,7 @@ CL_GenericHandle
=============
*/
static const char *CL_GenericHandle( int fileindex )
const char *CL_GenericHandle( int fileindex )
{
if( fileindex < 0 || fileindex >= MAX_CUSTOM )
return 0;
@@ -142,6 +142,8 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
return 1;
#endif
return 0;
case PARM_SKY_SPHERE:
return FBitSet( world.flags, FWORLD_SKYSPHERE ) && !FBitSet( world.flags, FWORLD_CUSTOM_SKYBOX );
case PARAM_GAMEPAUSED:
return cl.paused;
case PARM_CLIENT_INGAME:
@@ -162,20 +164,6 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
return (intptr_t)world.deluxedata;
case PARM_SHADOWDATA:
return (intptr_t)world.shadowdata;
case PARM_FULLSCREEN:
return refState.fullScreen;
case PARM_WIDESCREEN:
return refState.wideScreen;
case PARM_SCREEN_WIDTH:
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 )
@@ -191,30 +179,26 @@ intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRe
return CL_IsThirdPerson();
case PARM_QUAKE_COMPATIBLE:
return Host_IsQuakeCompatible();
case PARM_PLAYER_INDEX:
return cl.playernum + 1;
case PARM_VIEWENT_INDEX:
return cl.viewentity;
case PARM_CONNSTATE:
return (int)cls.state;
case PARM_PLAYING_DEMO:
return cls.demoplayback;
case PARM_WATER_LEVEL:
return cl.local.waterlevel;
case PARM_MAX_CLIENTS:
return cl.maxclients;
case PARM_LOCAL_HEALTH:
return cl.local.health;
case PARM_LOCAL_GAME:
return Host_IsLocalGame();
case PARM_NUMENTITIES:
return pfnNumberOfEntities();
case PARM_GET_CLIENT_PTR:
return (intptr_t)&cl.time; // with the offset
case PARM_GET_HOST_PTR:
return (intptr_t)&host.realtime; // with the offset
case PARM_GET_WORLD_PTR:
return (intptr_t)&world;
case PARM_GET_MOVEVARS_PTR:
return (intptr_t)&clgame.movevars;
case PARM_GET_PALETTE_PTR:
return (intptr_t)&clgame.palette;
case PARM_GET_VIEWENT_PTR:
return (intptr_t)&clgame.viewent;
case PARM_NUMMODELS:
return cl.nummodels;
}
}
return 0;
@@ -347,7 +331,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

@@ -20,19 +20,18 @@ GNU General Public License for more details.
#include "input.h"
#include "library.h"
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( 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" );
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)" );
convar_t *scr_centertime;
convar_t *scr_loading;
convar_t *scr_download;
convar_t *scr_viewsize;
convar_t *cl_testlights;
convar_t *cl_allow_levelshots;
convar_t *cl_levelshot_name;
static convar_t *cl_envshot_size;
convar_t *v_dark;
static convar_t *net_speeds;
static convar_t *cl_showfps;
static convar_t *cl_showpos;
typedef struct
{
@@ -60,7 +59,7 @@ void SCR_DrawFPS( int height )
char fpsstring[64];
int offset;
if( cls.state != ca_active || !cl_showfps.value || cl.background )
if( cls.state != ca_active || !cl_showfps->value || cl.background )
return;
switch( cls.scrshot_action )
@@ -96,7 +95,7 @@ void SCR_DrawFPS( int height )
if( curfps < minfps ) minfps = curfps;
if( curfps > maxfps ) maxfps = curfps;
if( cl_showfps.value == 2 )
if( cl_showfps->value == 2 )
Q_snprintf( fpsstring, sizeof( fpsstring ), "fps: ^1%4i min, ^3%4i cur, ^2%4i max", minfps, curfps, maxfps );
else Q_snprintf( fpsstring, sizeof( fpsstring ), "%4i fps", curfps );
MakeRGBA( color, 255, 255, 255, 255 );
@@ -120,10 +119,10 @@ void SCR_DrawPos( void )
cl_entity_t *ent;
rgba_t color;
if( cls.state != ca_active || !cl_showpos.value || cl.background )
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
@@ -227,7 +164,7 @@ void SCR_NetSpeeds( void )
if( !host.allow_console )
return;
if( !net_speeds.value || cls.state != ca_active )
if( !net_speeds->value || cls.state != ca_active )
return;
// prevent to get too big values at max
@@ -315,7 +252,7 @@ VID_WriteOverviewScript
Create overview script file
===============
*/
static void VID_WriteOverviewScript( void )
void VID_WriteOverviewScript( void )
{
ref_overview_t *ov = &clgame.overView;
string filename;
@@ -351,14 +288,9 @@ void SCR_MakeScreenShot( void )
qboolean iRet = false;
int viewsize;
if( cls.scrshot_action == scrshot_inactive )
return;
if( cls.envshot_viewsize > 0 )
viewsize = cls.envshot_viewsize;
else viewsize = cl_envshot_size.value;
V_CheckGamma();
else viewsize = cl_envshot_size->value;
switch( cls.scrshot_action )
{
@@ -385,6 +317,8 @@ void SCR_MakeScreenShot( void )
if( iRet )
VID_WriteOverviewScript(); // store overview script too
break;
case scrshot_inactive:
return;
}
// report
@@ -408,19 +342,15 @@ void SCR_MakeScreenShot( void )
SCR_DrawPlaque
================
*/
static qboolean SCR_DrawPlaque( void )
void SCR_DrawPlaque( void )
{
if(( cl_allow_levelshots.value && !cls.changelevel ) || cl.background )
if(( cl_allow_levelshots->value && !cls.changelevel ) || cl.background )
{
int levelshot = ref.dllFuncs.GL_LoadTexture( cl_levelshot_name.string, NULL, 0, TF_IMAGE );
int levelshot = ref.dllFuncs.GL_LoadTexture( cl_levelshot_name->string, NULL, 0, TF_IMAGE );
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 +360,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 +381,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();
}
@@ -475,7 +413,7 @@ void SCR_EndLoadingPlaque( void )
SCR_AddDirtyPoint
=================
*/
static void SCR_AddDirtyPoint( int x, int y )
void SCR_AddDirtyPoint( int x, int y )
{
if( x < scr_dirty.x1 ) scr_dirty.x1 = x;
if( x > scr_dirty.x2 ) scr_dirty.x2 = x;
@@ -504,7 +442,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 +520,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 +530,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 +540,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();
}
/*
@@ -626,7 +558,7 @@ void SCR_LoadCreditsFont( void )
{
cl_font_t *const font = &cls.creditsFont;
qboolean success = false;
float scale = hud_fontscale.value;
float scale = hud_fontscale->value;
dword crc = 0;
// replace default gfx.wad textures by current charset's font
@@ -638,15 +570,15 @@ void SCR_LoadCreditsFont( void )
"creditsfont_%s.fnt", Cvar_VariableString( "con_charset" )) > 0 )
{
if( FS_FileExists( charsetFnt, false ))
success = Con_LoadVariableWidthFont( charsetFnt, font, scale, &hud_fontrender, TF_FONT );
success = Con_LoadVariableWidthFont( charsetFnt, font, scale, kRenderTransAdd, TF_FONT );
}
}
if( !success )
success = Con_LoadVariableWidthFont( "gfx/creditsfont.fnt", font, scale, &hud_fontrender, TF_FONT );
success = Con_LoadVariableWidthFont( "gfx/creditsfont.fnt", font, scale, kRenderTransAdd, TF_FONT );
if( !success )
success = Con_LoadFixedWidthFont( "gfx/conchars", font, scale, &hud_fontrender, TF_FONT );
success = Con_LoadFixedWidthFont( "gfx/conchars", font, scale, kRenderTransAdd, TF_FONT );
// copy font size for client.dll
if( success )
@@ -668,7 +600,7 @@ SCR_InstallParticlePalette
INTERNAL RESOURCE
================
*/
static void SCR_InstallParticlePalette( void )
void SCR_InstallParticlePalette( void )
{
rgbdata_t *pic;
int i;
@@ -714,21 +646,21 @@ void SCR_RegisterTextures( void )
// register gfx.wad images
if( FS_FileExists( "gfx/paused.lmp", false ))
cls.pauseIcon = ref.dllFuncs.GL_LoadTexture( "gfx/paused.lmp", NULL, 0, TF_IMAGE|TF_ALLOW_NEAREST );
cls.pauseIcon = ref.dllFuncs.GL_LoadTexture( "gfx/paused.lmp", NULL, 0, TF_IMAGE );
else if( FS_FileExists( "gfx/pause.lmp", false ))
cls.pauseIcon = ref.dllFuncs.GL_LoadTexture( "gfx/pause.lmp", NULL, 0, TF_IMAGE|TF_ALLOW_NEAREST );
cls.pauseIcon = ref.dllFuncs.GL_LoadTexture( "gfx/pause.lmp", NULL, 0, TF_IMAGE );
if( FS_FileExists( "gfx/lambda.lmp", false ))
{
if( cl_allow_levelshots.value )
cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/lambda.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE|TF_ALLOW_NEAREST );
else cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/lambda.lmp", NULL, 0, TF_IMAGE|TF_ALLOW_NEAREST );
if( cl_allow_levelshots->value )
cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/lambda.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE );
else cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/lambda.lmp", NULL, 0, TF_IMAGE );
}
else if( FS_FileExists( "gfx/loading.lmp", false ))
{
if( cl_allow_levelshots.value )
cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/loading.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE|TF_ALLOW_NEAREST );
else cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/loading.lmp", NULL, 0, TF_IMAGE|TF_ALLOW_NEAREST );
if( cl_allow_levelshots->value )
cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/loading.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE );
else cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/loading.lmp", NULL, 0, TF_IMAGE );
}
cls.tileImage = ref.dllFuncs.GL_LoadTexture( "gfx/backtile.lmp", NULL, 0, TF_NOMIPMAP );
@@ -741,9 +673,9 @@ SCR_SizeUp_f
Keybinding command
=================
*/
static void SCR_SizeUp_f( void )
void SCR_SizeUp_f( void )
{
Cvar_SetValue( "viewsize", Q_min( scr_viewsize.value + 10, 120 ));
Cvar_SetValue( "viewsize", Q_min( scr_viewsize->value + 10, 120 ));
}
@@ -754,9 +686,9 @@ SCR_SizeDown_f
Keybinding command
=================
*/
static void SCR_SizeDown_f( void )
void SCR_SizeDown_f( void )
{
Cvar_SetValue( "viewsize", Q_max( scr_viewsize.value - 10, 30 ));
Cvar_SetValue( "viewsize", Q_max( scr_viewsize->value - 10, 30 ));
}
/*
@@ -783,7 +715,9 @@ void SCR_VidInit( void )
// notify vgui about screen size change
if( clgame.hInstance )
{
VGui_Startup( refState.width, refState.height );
// do not pass client pointer, we do not want to
// re-initialize vgui2
VGui_Startup( NULL, refState.width, refState.height );
}
CL_ClearSpriteTextures(); // now all hud sprites are invalid
@@ -794,7 +728,6 @@ void SCR_VidInit( void )
// restart console size
Con_VidInit ();
Touch_NotifyResize();
}
/*
@@ -806,21 +739,18 @@ void SCR_Init( void )
{
if( scr_init ) return;
Cvar_RegisterVariable( &scr_centertime );
Cvar_RegisterVariable( &cl_levelshot_name );
Cvar_RegisterVariable( &cl_allow_levelshots );
Cvar_RegisterVariable( &scr_loading );
Cvar_RegisterVariable( &scr_download );
Cvar_RegisterVariable( &cl_testlights );
Cvar_RegisterVariable( &cl_envshot_size );
Cvar_RegisterVariable( &v_dark );
Cvar_RegisterVariable( &scr_viewsize );
Cvar_RegisterVariable( &net_speeds );
Cvar_RegisterVariable( &cl_showfps );
Cvar_RegisterVariable( &cl_showpos );
#ifdef _DEBUG
Cvar_RegisterVariable( &cl_showents );
#endif // NDEBUG
scr_centertime = Cvar_Get( "scr_centertime", "2.5", 0, "centerprint hold time" );
cl_levelshot_name = Cvar_Get( "cl_levelshot_name", "*black", 0, "contains path to current levelshot" );
cl_allow_levelshots = Cvar_Get( "allow_levelshots", "0", FCVAR_ARCHIVE, "allow engine to use indivdual levelshots instead of 'loading' image" );
scr_loading = Cvar_Get( "scr_loading", "0", 0, "loading bar progress" );
scr_download = Cvar_Get( "scr_download", "-1", 0, "downloading bar progress" );
cl_testlights = Cvar_Get( "cl_testlights", "0", 0, "test dynamic lights" );
cl_envshot_size = Cvar_Get( "cl_envshot_size", "256", FCVAR_ARCHIVE, "envshot size of cube side" );
v_dark = Cvar_Get( "v_dark", "0", 0, "starts level from dark screen" );
scr_viewsize = Cvar_Get( "viewsize", "120", FCVAR_ARCHIVE, "screen size" );
net_speeds = Cvar_Get( "net_speeds", "0", FCVAR_ARCHIVE, "show network packets" );
cl_showfps = Cvar_Get( "cl_showfps", "0", FCVAR_ARCHIVE, "show client fps" );
cl_showpos = Cvar_Get( "cl_showpos", "0", FCVAR_ARCHIVE, "show local player position and velocity" );
// register our commands
Cmd_AddCommand( "skyname", CL_SetSky_f, "set new skybox by basename" );

View File

@@ -57,7 +57,35 @@ const char *cl_default_sprites[] =
"sprites/shellchrome.spr",
};
static void CL_PlayerDecal( int playerIndex, int textureIndex, int entityIndex, float *pos );
const char *cl_player_shell_sounds[] =
{
"player/pl_shell1.wav",
"player/pl_shell2.wav",
"player/pl_shell3.wav",
};
const char *cl_weapon_shell_sounds[] =
{
"weapons/sshell1.wav",
"weapons/sshell2.wav",
"weapons/sshell3.wav",
};
const char *cl_ricochet_sounds[] =
{
"weapons/ric1.wav",
"weapons/ric2.wav",
"weapons/ric3.wav",
"weapons/ric4.wav",
"weapons/ric5.wav",
};
const char *cl_explode_sounds[] =
{
"weapons/explode3.wav",
"weapons/explode4.wav",
"weapons/explode5.wav",
};
/*
================
@@ -118,7 +146,6 @@ client resources not precached by server
*/
void CL_AddClientResources( void )
{
const char *snd;
char filepath[MAX_QPATH];
int i;
@@ -134,37 +161,37 @@ void CL_AddClientResources( void )
}
// then check sounds
for( i = 0; ( snd = SoundList_Get( BouncePlayerShell, i )); i++ )
for( i = 0; i < ARRAYSIZE( cl_player_shell_sounds ); i++ )
{
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", snd );
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", cl_player_shell_sounds[i] );
if( !FS_FileExists( filepath, false ))
CL_AddClientResource( snd, t_sound );
CL_AddClientResource( cl_player_shell_sounds[i], t_sound );
}
for( i = 0; ( snd = SoundList_Get( BounceWeaponShell, i )); i++ )
for( i = 0; i < ARRAYSIZE( cl_weapon_shell_sounds ); i++ )
{
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", snd );
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", cl_weapon_shell_sounds[i] );
if( !FS_FileExists( filepath, false ))
CL_AddClientResource( snd, t_sound );
CL_AddClientResource( cl_weapon_shell_sounds[i], t_sound );
}
for( i = 0; ( snd = SoundList_Get( Explode, i )); i++ )
for( i = 0; i < ARRAYSIZE( cl_explode_sounds ); i++ )
{
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", snd );
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", cl_explode_sounds[i] );
if( !FS_FileExists( filepath, false ))
CL_AddClientResource( snd, t_sound );
CL_AddClientResource( cl_explode_sounds[i], t_sound );
}
#if 0 // ric sounds was precached by server-side
for( i = 0; ( snd = SoundList_Get( Ricochet, i )); i++ )
for( i = 0; i < ARRAYSIZE( cl_ricochet_sounds ); i++ )
{
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", snd );
Q_snprintf( filepath, sizeof( filepath ), DEFAULT_SOUNDPATH "%s", cl_ricochet_sounds[i] );
if( !FS_FileExists( filepath, false ))
CL_AddClientResource( snd, t_sound );
CL_AddClientResource( cl_ricochet_sounds[i], t_sound );
}
#endif
}
@@ -228,7 +255,7 @@ CL_PrepareTEnt
set default values
==============
*/
static void CL_PrepareTEnt( TEMPENTITY *pTemp, model_t *pmodel )
void CL_PrepareTEnt( TEMPENTITY *pTemp, model_t *pmodel )
{
int frameCount = 0;
int modelIndex = 0;
@@ -269,10 +296,10 @@ CL_TempEntPlaySound
play collide sound
==============
*/
static void CL_TempEntPlaySound( TEMPENTITY *pTemp, float damp )
void CL_TempEntPlaySound( TEMPENTITY *pTemp, float damp )
{
float fvol;
const char *soundname = NULL;
char soundname[32];
qboolean isshellcasing = false;
int zvel;
@@ -283,39 +310,36 @@ static void CL_TempEntPlaySound( TEMPENTITY *pTemp, float damp )
switch( pTemp->hitSound )
{
case BOUNCE_GLASS:
soundname = SoundList_GetRandom( BounceGlass );
Q_snprintf( soundname, sizeof( soundname ), "debris/glass%i.wav", COM_RandomLong( 1, 4 ));
break;
case BOUNCE_METAL:
soundname = SoundList_GetRandom( BounceMetal );
Q_snprintf( soundname, sizeof( soundname ), "debris/metal%i.wav", COM_RandomLong( 1, 6 ));
break;
case BOUNCE_FLESH:
soundname = SoundList_GetRandom( BounceFlesh );
Q_snprintf( soundname, sizeof( soundname ), "debris/flesh%i.wav", COM_RandomLong( 1, 7 ));
break;
case BOUNCE_WOOD:
soundname = SoundList_GetRandom( BounceWood );
Q_snprintf( soundname, sizeof( soundname ), "debris/wood%i.wav", COM_RandomLong( 1, 4 ));
break;
case BOUNCE_SHRAP:
soundname = SoundList_GetRandom( Ricochet );
Q_strncpy( soundname, cl_ricochet_sounds[COM_RandomLong( 0, 4 )], sizeof( soundname ) );
break;
case BOUNCE_SHOTSHELL:
soundname = SoundList_GetRandom( BounceWeaponShell );
Q_strncpy( soundname, cl_weapon_shell_sounds[COM_RandomLong( 0, 2 )], sizeof( soundname ) );
isshellcasing = true; // shell casings have different playback parameters
fvol = 0.5f;
break;
case BOUNCE_SHELL:
soundname = SoundList_GetRandom( BouncePlayerShell );
Q_strncpy( soundname, cl_player_shell_sounds[COM_RandomLong( 0, 2 )], sizeof( soundname ) );
isshellcasing = true; // shell casings have different playback parameters
break;
case BOUNCE_CONCRETE:
soundname = SoundList_GetRandom( BounceConcrete );
Q_snprintf( soundname, sizeof( soundname ), "debris/concrete%i.wav", COM_RandomLong( 1, 3 ));
break;
default: // null sound
return;
}
if( !soundname )
return;
zvel = abs( pTemp->entity.baseline.origin[2] );
// only play one out of every n
@@ -356,7 +380,7 @@ CL_TEntAddEntity
add entity to renderlist
==============
*/
static int CL_TempEntAddEntity( cl_entity_t *pEntity )
int CL_TempEntAddEntity( cl_entity_t *pEntity )
{
vec3_t mins, maxs;
@@ -408,7 +432,7 @@ CL_TEntAddEntity
free the first low priority tempent it finds.
==============
*/
static qboolean CL_FreeLowPriorityTempEnt( void )
qboolean CL_FreeLowPriorityTempEnt( void )
{
TEMPENTITY *pActive = cl_active_tents;
TEMPENTITY *pPrev = NULL;
@@ -1465,7 +1489,7 @@ void GAME_EXPORT R_FunnelSprite( const vec3_t org, int modelIndex, int reverse )
===============
R_SparkEffect
Create a streaks + ricochet sprite
Create a streaks + richochet sprite
===============
*/
void GAME_EXPORT R_SparkEffect( const vec3_t pos, int count, int velocityMin, int velocityMax )
@@ -1481,25 +1505,18 @@ R_RicochetSound
Make a random ricochet sound
==============
*/
static void R_RicochetSoundByName( const vec3_t pos, const char *name )
static void R_RicochetSound_( const vec3_t pos, int sound )
{
sound_t handle;
handle = S_RegisterSound( name );
S_StartSound( pos, 0, CHAN_AUTO, handle, VOL_NORM, 1.0, 100, 0 );
}
sound_t handle;
static void R_RicochetSoundByIndex( const vec3_t pos, int idx )
{
const char *name = SoundList_Get( Ricochet, idx );
if( name )
R_RicochetSoundByName( pos, name );
handle = S_RegisterSound( cl_ricochet_sounds[sound] );
S_StartSound( pos, 0, CHAN_AUTO, handle, VOL_NORM, 1.0, 100, 0 );
}
void GAME_EXPORT R_RicochetSound( const vec3_t pos )
{
const char *name = SoundList_GetRandom( Ricochet );
if( name )
R_RicochetSoundByName( pos, name );
R_RicochetSound_( pos, COM_RandomLong( 0, 4 ));
}
/*
@@ -1646,12 +1663,8 @@ void GAME_EXPORT R_Explosion( vec3_t pos, int model, float scale, float framerat
if( !FBitSet( flags, TE_EXPLFLAG_NOSOUND ))
{
const char *name = SoundList_GetRandom( Explode );
if( name )
{
hSound = S_RegisterSound( name );
S_StartSound( pos, 0, CHAN_STATIC, hSound, VOL_NORM, 0.3f, PITCH_NORM, 0 );
}
hSound = S_RegisterSound( cl_explode_sounds[COM_RandomLong( 0, 2 )] );
S_StartSound( pos, 0, CHAN_STATIC, hSound, VOL_NORM, 0.3f, PITCH_NORM, 0 );
}
}
@@ -1894,7 +1907,6 @@ void CL_ParseTempEntity( sizebuf_t *msg )
cl_entity_t *pEnt;
dlight_t *dl;
sound_t hSound;
const char *name;
if( cls.legacymode )
iSize = MSG_ReadByte( msg );
@@ -1904,7 +1916,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
// this will probably be fatal anyway
if( iSize > sizeof( pbuf ))
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __func__ );
Con_Printf( S_ERROR "%s: Temp buffer overflow!\n", __FUNCTION__ );
// parse user message into buffer
MSG_ReadBytes( msg, pbuf, iSize );
@@ -1954,11 +1966,8 @@ void CL_ParseTempEntity( sizebuf_t *msg )
pos[2] = MSG_ReadCoord( &buf );
R_BlobExplosion( pos );
if(( name = SoundList_Get( Explode, 0 )))
{
hSound = S_RegisterSound( name );
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 1.0f, PITCH_NORM, 0 );
}
hSound = S_RegisterSound( cl_explode_sounds[0] );
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 1.0f, PITCH_NORM, 0 );
break;
case TE_SMOKE:
pos[0] = MSG_ReadCoord( &buf );
@@ -2011,11 +2020,8 @@ void CL_ParseTempEntity( sizebuf_t *msg )
dl->die = cl.time + 0.5;
dl->decay = 300;
if(( name = SoundList_Get( Explode, 0 )))
{
hSound = S_RegisterSound( name );
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 1.0f, PITCH_NORM, 0 );
}
hSound = S_RegisterSound( cl_explode_sounds[0] );
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 0.6f, PITCH_NORM, 0 );
break;
case TE_BSPDECAL:
case TE_DECAL:
@@ -2243,8 +2249,8 @@ void CL_ParseTempEntity( sizebuf_t *msg )
CL_DecalShoot( CL_DecalIndex( decalIndex ), entityIndex, 0, pos, 0 );
R_BulletImpactParticles( pos );
flags = COM_RandomLong( 0, 0x7fff );
if( flags < 0x3fff && ( count = SoundList_Count( Ricochet )))
R_RicochetSoundByIndex( pos, flags % count );
if( flags < 0x3fff )
R_RicochetSound_( pos, flags % 5 );
break;
case TE_SPRAY:
case TE_SPRITE_SPRAY:
@@ -2384,13 +2390,13 @@ void CL_ParseTempEntity( sizebuf_t *msg )
R_UserTracerParticle( pos, pos2, life, color, scale, 0, NULL );
break;
default:
Con_DPrintf( S_ERROR "%s: illegible TE message %i\n", __func__, type );
Con_DPrintf( S_ERROR "ParseTempEntity: illegible TE message %i\n", type );
break;
}
// throw warning
if( MSG_CheckOverflow( &buf ))
Con_DPrintf( S_WARN "%s: overflow TE message %i\n", __func__, type );
Con_DPrintf( S_WARN "ParseTempEntity: overflow TE message %i\n", type );
}
@@ -2408,7 +2414,7 @@ LIGHT STYLE MANAGEMENT
CL_ClearLightStyles
================
*/
static void CL_ClearLightStyles( void )
void CL_ClearLightStyles( void )
{
memset( cl.lightstyles, 0, sizeof( cl.lightstyles ));
}
@@ -2466,7 +2472,7 @@ dlight_t cl_elights[MAX_ELIGHTS];
CL_ClearDlights
================
*/
static void CL_ClearDlights( void )
void CL_ClearDlights( void )
{
memset( cl_dlights, 0, sizeof( cl_dlights ));
memset( cl_elights, 0, sizeof( cl_elights ));
@@ -2618,12 +2624,12 @@ CL_UpdateFlashlight
update client flashlight
================
*/
static void CL_UpdateFlashlight( cl_entity_t *ent )
void CL_UpdateFlashlight( cl_entity_t *ent )
{
vec3_t forward, view_ofs;
vec3_t vecSrc, vecEnd;
float falloff;
pmtrace_t trace;
pmtrace_t *trace;
cl_entity_t *hit;
dlight_t *dl;
@@ -2654,65 +2660,32 @@ static void CL_UpdateFlashlight( cl_entity_t *ent )
VectorAdd( ent->origin, view_ofs, vecSrc );
VectorMA( vecSrc, FLASHLIGHT_DISTANCE, forward, vecEnd );
trace = CL_TraceLine( vecSrc, vecEnd, PM_STUDIO_BOX );
trace = CL_VisTraceLine( vecSrc, vecEnd, PM_STUDIO_BOX );
// update flashlight endpos
dl = CL_AllocDlight( ent->index );
#if 1
hit = CL_GetEntityByIndex( clgame.pmove->physents[trace.ent].info );
hit = CL_GetEntityByIndex( clgame.pmove->visents[trace->ent].info );
if( hit && hit->model && ( hit->model->type == mod_alias || hit->model->type == mod_studio ))
VectorCopy( hit->origin, dl->origin );
else VectorCopy( trace.endpos, dl->origin );
else VectorCopy( trace->endpos, dl->origin );
#else
VectorCopy( trace->endpos, dl->origin );
#endif
// compute falloff
falloff = trace.fraction * FLASHLIGHT_DISTANCE;
falloff = trace->fraction * FLASHLIGHT_DISTANCE;
if( falloff < 500.0f ) falloff = 1.0f;
else falloff = 500.0f / falloff;
falloff *= falloff;
// apply brigthness to dlight
dl->color.r = dl->color.g = dl->color.b = bound( 0, falloff * 255, 255 );
dl->color.r = bound( 0, falloff * 255, 255 );
dl->color.g = bound( 0, falloff * 255, 255 );
dl->color.b = bound( 0, falloff * 255, 255 );
dl->die = cl.time + 0.01f; // die on next frame
dl->radius = 80;
}
static void R_EntityDimlight( cl_entity_t *ent, int key )
{
dlight_t *dl = CL_AllocDlight( key );
VectorCopy( ent->origin, dl->origin );
dl->color.r = dl->color.g = dl->color.b = 100;
dl->radius = COM_RandomFloat( 200.0f, 231.0f );
dl->die = cl.time + 0.001;
}
static void R_EntityLight( cl_entity_t *ent, int key )
{
dlight_t *dl = CL_AllocDlight( key );
VectorCopy( ent->origin, dl->origin );
dl->color.r = dl->color.g = dl->color.b = 100;
dl->radius = 200;
dl->die = cl.time + 0.001;
R_RocketFlare( ent->origin );
}
static void R_EntityBrightlight( cl_entity_t *ent, int key, int radius )
{
dlight_t *dl = CL_AllocDlight( key );
VectorCopy( ent->origin, dl->origin );
dl->origin[2] += 16.0f;
dl->color.r = dl->color.g = dl->color.b = 250;
if( !radius )
dl->radius = COM_RandomFloat( 400.0f, 431.0f );
else dl->radius = 400;
dl->die = cl.time + 0.001;
}
/*
================
CL_AddEntityEffects
@@ -2722,41 +2695,50 @@ apply various effects to entity origin or attachment
*/
void CL_AddEntityEffects( cl_entity_t *ent )
{
// players have special set of effects, from CL_LinkPlayers
if( ent->player && ent->index != cl.viewentity )
{
if( FBitSet( ent->curstate.effects, EF_BRIGHTLIGHT ))
R_EntityBrightlight( ent, ent->index /* 4 in GoldSrc */, 0 );
// yellow flies effect 'monster stuck in the wall'
if( FBitSet( ent->curstate.effects, EF_BRIGHTFIELD ) && !RP_LOCALCLIENT( ent ))
R_EntityParticles( ent );
if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
R_EntityDimlight( ent, ent->index /* 4 in GoldSrc */ );
}
else if( RP_LOCALCLIENT( ent ))
if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
{
// from CL_PlayerFlashlight
if( FBitSet( ent->curstate.effects, EF_BRIGHTLIGHT ))
R_EntityBrightlight( ent, ent->index /* 1 in GoldSrc */, 400 );
else if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
if( ent->player && !Host_IsQuakeCompatible( ))
{
CL_UpdateFlashlight( ent );
}
else
{
dlight_t *dl = CL_AllocDlight( ent->index );
dl->color.r = dl->color.g = dl->color.b = 100;
dl->radius = COM_RandomFloat( 200, 231 );
VectorCopy( ent->origin, dl->origin );
dl->die = cl.time + 0.001;
}
}
else
if( FBitSet( ent->curstate.effects, EF_BRIGHTLIGHT ))
{
// from CL_LinkPacketEntities
if( FBitSet( ent->curstate.effects, EF_BRIGHTFIELD ))
R_EntityParticles( ent );
dlight_t *dl = CL_AllocDlight( ent->index );
dl->color.r = dl->color.g = dl->color.b = 250;
if( ent->player ) dl->radius = 400; // don't flickering
else dl->radius = COM_RandomFloat( 400, 431 );
VectorCopy( ent->origin, dl->origin );
dl->die = cl.time + 0.001;
dl->origin[2] += 16.0f;
}
if( FBitSet( ent->curstate.effects, EF_BRIGHTLIGHT ))
R_EntityBrightlight( ent, ent->index, 0 );
if( FBitSet( ent->curstate.effects, EF_DIMLIGHT ))
R_EntityDimlight( ent, ent->index );
if( FBitSet( ent->curstate.effects, EF_LIGHT ))
R_EntityLight( ent, ent->curstate.number );
// add light effect
if( FBitSet( ent->curstate.effects, EF_LIGHT ))
{
dlight_t *dl = CL_AllocDlight( ent->index );
dl->color.r = dl->color.g = dl->color.b = 100;
VectorCopy( ent->origin, dl->origin );
R_RocketFlare( ent->origin );
dl->die = cl.time + 0.001;
dl->radius = 200;
}
// studio models are handle muzzleflashes difference
if( FBitSet( ent->curstate.effects, EF_MUZZLEFLASH ) && ent->model && ent->model->type == mod_alias )
if( FBitSet( ent->curstate.effects, EF_MUZZLEFLASH ) && Mod_AliasExtradata( ent->model ))
{
dlight_t *dl = CL_AllocDlight( ent->index );
vec3_t fv;
@@ -2785,11 +2767,15 @@ void CL_AddModelEffects( cl_entity_t *ent )
vec3_t neworigin;
vec3_t oldorigin;
if( !ent->model || ent->player )
return;
if( !ent->model ) return;
if( ent->model->type != mod_alias && ent->model->type != mod_studio )
return;
switch( ent->model->type )
{
case mod_alias:
case mod_studio:
break;
default: return;
}
if( cls.demoplayback == DEMO_QUAKE1 )
{
@@ -2809,15 +2795,19 @@ void CL_AddModelEffects( cl_entity_t *ent )
if( FBitSet( ent->model->flags, STUDIO_GIB ))
R_RocketTrail( oldorigin, neworigin, 2 );
else if( FBitSet( ent->model->flags, STUDIO_ZOMGIB ))
if( FBitSet( ent->model->flags, STUDIO_ZOMGIB ))
R_RocketTrail( oldorigin, neworigin, 4 );
else if( FBitSet( ent->model->flags, STUDIO_TRACER ))
if( FBitSet( ent->model->flags, STUDIO_TRACER ))
R_RocketTrail( oldorigin, neworigin, 3 );
else if( FBitSet( ent->model->flags, STUDIO_TRACER2 ))
if( FBitSet( ent->model->flags, STUDIO_TRACER2 ))
R_RocketTrail( oldorigin, neworigin, 5 );
else if( FBitSet( ent->model->flags, STUDIO_ROCKET ))
if( FBitSet( ent->model->flags, STUDIO_ROCKET ))
{
dlight_t *dl = CL_AllocDlight( ent->curstate.number );
dlight_t *dl = CL_AllocDlight( ent->index );
dl->color.r = dl->color.g = dl->color.b = 200;
VectorCopy( ent->origin, dl->origin );
@@ -2831,9 +2821,11 @@ void CL_AddModelEffects( cl_entity_t *ent )
R_RocketTrail( oldorigin, neworigin, 0 );
}
else if( FBitSet( ent->model->flags, STUDIO_GRENADE ))
if( FBitSet( ent->model->flags, STUDIO_GRENADE ))
R_RocketTrail( oldorigin, neworigin, 1 );
else if( FBitSet( ent->model->flags, STUDIO_TRACER3 ))
if( FBitSet( ent->model->flags, STUDIO_TRACER3 ))
R_RocketTrail( oldorigin, neworigin, 6 );
}
@@ -2851,10 +2843,10 @@ void CL_TestLights( void )
float f, r;
dlight_t *dl;
if( !cl_testlights.value )
if( !CVAR_TO_BOOL( cl_testlights ))
return;
numLights = bound( 1, cl_testlights.value, MAX_DLIGHTS );
numLights = bound( 1, cl_testlights->value, MAX_DLIGHTS );
AngleVectors( cl.viewangles, forward, right, NULL );
for( i = 0; i < numLights; i++ )
@@ -2913,7 +2905,7 @@ CL_PlayerDecal
spray custom colored decal (clan logo etc)
===============
*/
static void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, float *pos )
void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, float *pos )
{
int textureIndex = 0;
customization_t *pCust = NULL;
@@ -2927,26 +2919,16 @@ static void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, flo
{
if( !pCust->nUserData1 )
{
int sprayTextureIndex;
char decalname[MAX_VA_STRING];
int width, height;
Q_snprintf( decalname, sizeof( decalname ), "player%dlogo%d", playernum, customIndex );
textureIndex = ref.dllFuncs.GL_FindTexture( decalname );
if( textureIndex != 0 )
ref.dllFuncs.GL_FreeTexture( textureIndex );
pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL );
width = REF_GET_PARM( PARM_TEX_WIDTH, pCust->nUserData1 );
height = REF_GET_PARM( PARM_TEX_HEIGHT, pCust->nUserData1 );
if( width > cl_logomaxdim.value || height > cl_logomaxdim.value )
sprayTextureIndex = ref.dllFuncs.GL_FindTexture( decalname );
if( sprayTextureIndex != 0 )
{
double scale = cl_logomaxdim.value / Q_max( width, height );
width = round( width * scale );
height = round( height * scale );
ref.dllFuncs.R_OverrideTextureSourceSize( pCust->nUserData1, width, height ); // default custom decal from HL1
ref.dllFuncs.GL_FreeTexture( sprayTextureIndex );
}
pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL );
}
textureIndex = pCust->nUserData1;
}
@@ -2991,47 +2973,8 @@ int GAME_EXPORT CL_DecalIndex( int id )
if( cl.decal_index[id] == 0 )
{
int gl_texturenum = 0;
Image_SetForceFlags( IL_LOAD_DECAL );
if( Mod_AllowMaterials( ))
{
string decalname;
if( Q_snprintf( decalname, sizeof( decalname ), "materials/decals/%s.tga", host.draw_decals[id] ) > 0 )
{
if( g_fsapi.FileExists( decalname, false ))
{
gl_texturenum = ref.dllFuncs.GL_LoadTexture( decalname, NULL, 0, TF_DECAL );
if( host_allow_materials.value == 2.0f )
Con_Printf( "Looking for %s decal replacement...%s (%s)\n", host.draw_decals[id], gl_texturenum != 0 ? S_GREEN "OK" : S_RED "FAIL", decalname );
}
else if( host_allow_materials.value == 2.0f )
Con_Printf( "Looking for %s decal replacement..." S_YELLOW "MISS (%s)\n", host.draw_decals[id], decalname );
}
else if( host_allow_materials.value == 2.0f )
Con_Printf( "Looking for %s decal replacement..." S_YELLOW "MISS (overflow)\n", host.draw_decals[id] );
if( gl_texturenum )
{
byte *fin;
Q_snprintf( decalname, sizeof( decalname ), "decals.wad/%s", host.draw_decals[id] );
if(( fin = g_fsapi.LoadFile( decalname, NULL, false )) != NULL )
{
mip_t *mip = (mip_t *)fin;
ref.dllFuncs.R_OverrideTextureSourceSize( gl_texturenum, mip->width, mip->height );
Mem_Free( fin );
}
}
}
if( !gl_texturenum )
gl_texturenum = ref.dllFuncs.GL_LoadTexture( host.draw_decals[id], NULL, 0, TF_DECAL );
cl.decal_index[id] = gl_texturenum;
cl.decal_index[id] = ref.dllFuncs.GL_LoadTexture( host.draw_decals[id], NULL, 0, TF_DECAL );
Image_ClearForceFlags();
}

View File

@@ -81,6 +81,7 @@ 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 );
void CL_UpdateFlashlight( cl_entity_t *pEnt );
void CL_AddEntityEffects( cl_entity_t *ent );
void CL_AddModelEffects( cl_entity_t *ent );
void CL_DecalShoot( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags );

View File

@@ -68,7 +68,7 @@ qboolean SCR_NextMovie( void )
return true;
}
static void SCR_CreateStartupVids( void )
void SCR_CreateStartupVids( void )
{
file_t *f;
@@ -202,6 +202,7 @@ SCR_PlayCinematic
*/
qboolean SCR_PlayCinematic( const char *arg )
{
string path;
const char *fullpath;
fullpath = FS_GetDiskPath( arg, false );

View File

@@ -29,7 +29,7 @@ V_CalcViewRect
calc frame rectangle (Quake1 style)
===============
*/
static void V_CalcViewRect( void )
void V_CalcViewRect( void )
{
qboolean full = false;
int sb_lines;
@@ -39,7 +39,7 @@ static void V_CalcViewRect( void )
{
// intermission is always full screen
if( cl.intermission ) size = 120.0f;
else size = scr_viewsize.value;
else size = scr_viewsize->value;
if( size >= 120.0f )
sb_lines = 0; // no status bar at all
@@ -47,12 +47,12 @@ static void V_CalcViewRect( void )
sb_lines = 24; // no inventory
else sb_lines = 48;
if( scr_viewsize.value >= 100.0f )
if( scr_viewsize->value >= 100.0f )
{
full = true;
size = 100.0f;
}
else size = scr_viewsize.value;
else size = scr_viewsize->value;
if( cl.intermission )
{
@@ -88,7 +88,7 @@ static void V_CalcViewRect( void )
V_SetupViewModel
===============
*/
static void V_SetupViewModel( void )
void V_SetupViewModel( void )
{
cl_entity_t *view = &clgame.viewent;
player_info_t *info = &cl.players[cl.playernum];
@@ -118,7 +118,7 @@ static void V_SetupViewModel( void )
V_SetRefParams
===============
*/
static void V_SetRefParams( ref_params_t *fd )
void V_SetRefParams( ref_params_t *fd )
{
memset( fd, 0, sizeof( ref_params_t ));
@@ -144,7 +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 );
fd->viewsize = scr_viewsize.value;
fd->viewsize = scr_viewsize->value;
VectorCopy( cl.punchangle, fd->punchangle );
fd->maxclients = cl.maxclients;
@@ -182,7 +182,7 @@ V_MergeOverviewRefdef
merge refdef with overview settings
===============
*/
static void V_RefApplyOverview( ref_viewpass_t *rvp )
void V_RefApplyOverview( ref_viewpass_t *rvp )
{
ref_overview_t *ov = &clgame.overView;
float aspect;
@@ -281,7 +281,7 @@ static void V_AdjustFov( float *fov_x, float *fov_y, float width, float height,
V_GetRefParams
=============
*/
static void V_GetRefParams( ref_params_t *fd, ref_viewpass_t *rvp )
void V_GetRefParams( ref_params_t *fd, ref_viewpass_t *rvp )
{
// part1: deniable updates
VectorCopy( fd->simvel, cl.simvel );
@@ -311,7 +311,7 @@ static void V_GetRefParams( ref_params_t *fd, ref_viewpass_t *rvp )
rvp->fov_y = V_CalcFov( &rvp->fov_x, clgame.viewport[2], clgame.viewport[3] );
// adjust FOV for widescreen
if( refState.wideScreen && r_adjust_fov.value )
if( refState.wideScreen && r_adjust_fov->value )
V_AdjustFov( &rvp->fov_x, &rvp->fov_y, clgame.viewport[2], clgame.viewport[3], false );
rvp->flags = 0;
@@ -339,16 +339,14 @@ qboolean V_PreRender( void )
// if the screen is disabled (loading plaque is up)
if( cls.disable_screen )
{
if(( host.realtime - cls.disable_screen ) > cl_timeout.value )
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;
}
V_CheckGamma();
ref.dllFuncs.R_BeginFrame( !cl.paused && ( cls.state == ca_active ));
GL_UpdateSwapInterval( );
@@ -366,13 +364,11 @@ V_RenderView
*/
void V_RenderView( void )
{
// HACKHACK: make ref params static
// not really critical but allows client.dll to take address of refdef and don't trigger ASan
static ref_params_t rp;
ref_params_t rp;
ref_viewpass_t rvp;
int viewnum = 0;
if( !cl.video_prepped || ( !ui_renderworld.value && UI_IsVisible() && !cl.background ))
if( !cl.video_prepped || ( !ui_renderworld->value && UI_IsVisible() && !cl.background ))
return; // still loading
V_CalcViewRect (); // compute viewport rectangle
@@ -408,14 +404,14 @@ void V_RenderView( void )
#define NODE_INTERVAL_X(x) (x * 16.0f)
#define NODE_INTERVAL_Y(x) (x * 16.0f)
static void R_DrawLeafNode( float x, float y, float scale )
void R_DrawLeafNode( float x, float y, float scale )
{
float downScale = scale * 0.25f;// * POINT_SIZE;
ref.dllFuncs.R_DrawStretchPic( x - downScale * 0.5f, y - downScale * 0.5f, downScale, downScale, 0, 0, 1, 1, R_GetBuiltinTexture( REF_PARTICLE_TEXTURE ) );
}
static void R_DrawNodeConnection( float x, float y, float x2, float y2 )
void R_DrawNodeConnection( float x, float y, float x2, float y2 )
{
ref.dllFuncs.Begin( TRI_LINES );
ref.dllFuncs.Vertex3f( x, y, 0 );
@@ -423,7 +419,7 @@ static void R_DrawNodeConnection( float x, float y, float x2, float y2 )
ref.dllFuncs.End( );
}
static void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes, mleaf_t *viewleaf )
void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes, mleaf_t *viewleaf )
{
float downScale = scale * 0.8f;
@@ -470,13 +466,13 @@ static void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int show
world.recursion_level--;
}
static void R_ShowTree( void )
void R_ShowTree( void )
{
float x = (float)((refState.width - (int)POINT_SIZE) >> 1);
float y = NODE_INTERVAL_Y(1.0f);
mleaf_t *viewleaf;
if( !cl.worldmodel || !r_showtree.value )
if( !cl.worldmodel || !CVAR_TO_BOOL( r_showtree ))
return;
world.recursion_level = 0;
@@ -506,6 +502,7 @@ V_PostRender
*/
void V_PostRender( void )
{
static double oldtime;
qboolean draw_2d = false;
ref.dllFuncs.R_AllowFog( false );
@@ -532,7 +529,6 @@ void V_PostRender( void )
SCR_RSpeeds();
SCR_NetSpeeds();
SCR_DrawPos();
SCR_DrawEnts();
SCR_DrawNetGraph();
SV_DrawOrthoTriangles();
CL_DrawDemoRecording();
@@ -551,8 +547,5 @@ void V_PostRender( void )
SCR_MakeScreenShot();
ref.dllFuncs.R_AllowFog( true );
Platform_SetTimer( 0.0f );
ref.dllFuncs.R_EndFrame();
V_CheckGammaEnd();
}

View File

@@ -174,26 +174,6 @@ typedef struct
// at every server map change
typedef struct
{
// ==== shared through RefAPI's ref_client_t ====
double time; // this is the time value that the client
// is rendering at. always <= cls.realtime
// a lerp point for other data
double oldtime; // previous cl.time, time-oldtime is used
// to decay light values and smooth step ups
int viewentity;
// server state information
int playernum;
int maxclients;
int nummodels;
model_t *models[MAX_MODELS+1]; // precached models (plus sentinel slot)
qboolean paused;
vec3_t simorg; // predicted origin
// ==== shared through RefAPI's ref_client_t ===
int servercount; // server identification for prespawns
int validsequence; // this is the sequence number of the last good
// world snapshot/update we got. If this is 0, we can't
@@ -203,6 +183,7 @@ typedef struct
qboolean video_prepped; // false if on new level or new ref dll
qboolean audio_prepped; // false if on new level or new snd dll
qboolean paused;
int delta_sequence; // acknowledged sequence number
@@ -224,12 +205,17 @@ typedef struct
runcmd_t commands[MULTIPLAYER_BACKUP]; // each mesage will send several old cmds
local_state_t predicted_frames[MULTIPLAYER_BACKUP]; // local client state
double time; // this is the time value that the client
// is rendering at. always <= cls.realtime
// a lerp point for other data
double oldtime; // previous cl.time, time-oldtime is used
// to decay light values and smooth step ups
double timedelta; // floating delta between two updates
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...
@@ -237,6 +223,7 @@ typedef struct
// player final info
usercmd_t *cmd; // cl.commands[outgoing_sequence].cmd
int viewentity;
vec3_t viewangles;
vec3_t viewheight;
vec3_t punchangle;
@@ -249,9 +236,14 @@ typedef struct
float addangletotal;
float prevaddangletotal;
// predicted velocity
// predicted origin and velocity
vec3_t simorg;
vec3_t simvel;
// server state information
int playernum;
int maxclients;
entity_state_t instanced_baseline[MAX_CUSTOM_BASELINES];
int instanced_baseline_count;
@@ -259,6 +251,8 @@ typedef struct
char event_precache[MAX_EVENTS][MAX_QPATH];
char files_precache[MAX_CUSTOM][MAX_QPATH];
lightstyle_t lightstyles[MAX_LIGHTSTYLES];
model_t *models[MAX_MODELS+1]; // precached models (plus sentinel slot)
int nummodels;
int numfiles;
consistency_t consistency_list[MAX_MODELS];
@@ -276,8 +270,6 @@ typedef struct
model_t *worldmodel; // pointer to world
int lostpackets; // count lost packets and show dialog in menu
double frametime_remainder;
} client_t;
/*
@@ -309,14 +301,6 @@ typedef enum
CL_CHANGELEVEL, // draw 'loading' during changelevel
} scrstate_t;
typedef enum
{
PROTO_CURRENT = 0, // Xash3D 49
PROTO_LEGACY = 1, // Xash3D 48
PROTO_QUAKE = 2, // Quake 15
PROTO_GOLDSRC = 3, // GoldSrc 48
} connprotocol_t;
typedef struct
{
char name[32];
@@ -352,7 +336,8 @@ typedef struct
byte charWidths[256]; // scaled widths
int charHeight; // scaled height
int type; // fixed width font or variable
convar_t *rendermode; // user-defined default rendermode
int rendermode; // default rendermode
qboolean nearest; // nearest filtering enabled
qboolean valid; // all rectangles are valid
} cl_font_t;
@@ -438,6 +423,13 @@ typedef struct
float applied_angle;
} screen_shake_t;
typedef enum
{
NET_REQUEST_CANCEL = 0, // request was cancelled for some reasons
NET_REQUEST_GAMEUI, // called from GameUI
NET_REQUEST_CLIENT, // called from Client
} net_request_type_t;
typedef struct
{
net_response_t resp;
@@ -499,7 +491,9 @@ typedef struct
client_textmessage_t *titles; // title messages, not network messages
int numTitles;
net_request_type_t request_type; // filter the requests
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
net_request_t *master_request; // queued master request
efrag_t *free_efrags; // linked efrags
cl_entity_t viewent; // viewmodel
@@ -528,7 +522,7 @@ typedef struct
int logo_yres;
float logo_length;
qboolean use_extended_api;
qboolean use_text_api;
} gameui_static_t;
typedef struct
@@ -549,8 +543,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
@@ -629,19 +627,14 @@ typedef struct
file_t *demofile;
file_t *demoheader; // contain demo startup info in case we record a demo on this level
qboolean internetservers_wait; // internetservers is waiting for dns request
qboolean internetservers_pending; // if true, clean master server pings
uint32_t internetservers_key; // compare key to validate master server reply
char internetservers_query[512]; // cached query
uint32_t internetservers_query_len;
qboolean internetservers_pending; // internetservers is waiting for dns request
// 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
@@ -661,55 +654,56 @@ extern gameui_static_t gameui;
// cvars
//
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_interp;
extern convar_t cl_nointerp;
extern convar_t cl_showerror;
extern convar_t cl_nosmooth;
extern convar_t cl_smoothtime;
extern convar_t cl_crosshair;
extern convar_t cl_testlights;
extern convar_t cl_cmdrate;
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_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 hud_fontscale;
extern convar_t hud_fontrender;
extern convar_t hud_scale;
extern convar_t hud_scale_minimal_width;
extern convar_t r_showtextures;
extern convar_t cl_bmodelinterp;
extern convar_t cl_lw; // local weapons
extern convar_t cl_charset;
extern convar_t cl_trace_stufftext;
extern convar_t cl_trace_messages;
extern convar_t cl_trace_events;
extern convar_t hud_utf8;
extern convar_t cl_showevents;
extern convar_t scr_centertime;
extern convar_t scr_viewsize;
extern convar_t scr_loading;
extern convar_t v_dark; // start from dark
extern convar_t net_graph;
extern convar_t rate;
extern convar_t m_ignore;
extern convar_t r_showtree;
extern convar_t ui_renderworld;
extern convar_t cl_fixmodelinterpolationartifacts;
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;
extern convar_t *cl_nosmooth;
extern convar_t *cl_smoothtime;
extern convar_t *cl_crosshair;
extern convar_t *cl_testlights;
extern convar_t *cl_cmdrate;
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_scale;
extern convar_t *gl_showtextures;
extern convar_t *cl_bmodelinterp;
extern convar_t *cl_lw; // local weapons
extern convar_t *cl_charset;
extern convar_t *cl_trace_messages;
extern convar_t *hud_utf8;
extern convar_t *cl_showevents;
extern convar_t *scr_centertime;
extern convar_t *scr_viewsize;
extern convar_t *scr_loading;
extern convar_t *v_dark; // start from dark
extern convar_t *net_graph;
extern convar_t *rate;
extern convar_t *m_ignore;
extern convar_t *r_showtree;
extern convar_t *ui_renderworld;
//=============================================================================
void CL_SetLightstyle( int style, const char* s, float f );
void CL_RunLightStyles( void );
void CL_DecayLights( void );
dlight_t *CL_GetDynamicLight( int number );
dlight_t *CL_GetEntityLight( int number );
@@ -720,8 +714,12 @@ dlight_t *CL_GetEntityLight( int number );
// cl_cmds.c
//
void CL_Quit_f( void );
void CL_GenericShot_f( void );
void CL_ScreenShot_f( void );
void CL_SnapShot_f( void );
void CL_PlayCDTrack_f( void );
void CL_EnvShot_f( void );
void CL_SkyShot_f( void );
void CL_SaveShot_f( void );
void CL_LevelShot_f( void );
void CL_SetSky_f( void );
void SCR_Viewpos_f( void );
@@ -742,6 +740,8 @@ void CL_ClearResourceLists( void );
void CL_Parse_Debug( qboolean enable );
void CL_Parse_RecordCommand( int cmd, int startoffset );
void CL_ResetFrame( frame_t *frame );
void CL_WriteMessageHistory( void );
const char *CL_MsgInfo( int cmd );
//
// cl_efx.c
@@ -752,6 +752,7 @@ void CL_Particle( const vec3_t org, int color, float life, int zpos, int zvel );
// cl_main.c
//
void CL_Init( void );
void CL_SendCommand( void );
void CL_Disconnect_f( void );
void CL_ProcessFile( qboolean successfully_received, const char *filename );
void CL_WriteUsercmd( sizebuf_t *msg, int from, int to );
@@ -760,8 +761,10 @@ qboolean CL_PrecacheResources( void );
void CL_SetupOverviewParams( void );
void CL_UpdateFrameLerp( void );
int CL_IsDevOverviewMode( void );
void CL_PingServers_f( void );
void CL_SignonReply( void );
void CL_ClearState( void );
size_t CL_BuildMasterServerScanRequest( char *buf, size_t size, qboolean nat );
//
// cl_demo.c
@@ -777,6 +780,8 @@ void CL_CheckStartupDemos( void );
void CL_WriteDemoJumpTime( void );
void CL_CloseDemoHeader( void );
void CL_DemoCompleted( void );
void CL_StopPlayback( void );
void CL_StopRecord( void );
void CL_PlayDemo_f( void );
void CL_TimeDemo_f( void );
void CL_StartDemos_f( void );
@@ -784,7 +789,6 @@ void CL_Demos_f( void );
void CL_DeleteDemo_f( void );
void CL_Record_f( void );
void CL_Stop_f( void );
int CL_GetDemoComment( const char *demoname, char *comment );
//
// cl_events.c
@@ -792,9 +796,12 @@ int CL_GetDemoComment( const char *demoname, char *comment );
void CL_ParseEvent( sizebuf_t *msg );
void CL_ParseReliableEvent( sizebuf_t *msg );
void CL_SetEventIndex( const char *szEvName, int ev_index );
void CL_QueueEvent( int flags, int index, float delay, event_args_t *args );
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 );
void CL_RegisterEvent( int lastnum, const char *szEvName, pfnEventHook func );
void CL_BatchResourceRequest( qboolean initialize );
int CL_EstimateNeededResources( void );
void CL_ResetEvent( event_info_t *ei );
word CL_EventIndex( const char *name );
void CL_FireEvents( void );
@@ -803,10 +810,9 @@ void CL_FireEvents( void );
// cl_font.c
//
qboolean CL_FixedFont( cl_font_t *font );
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags );
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, convar_t *rendermode, uint texFlags );
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags );
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags );
void CL_FreeFont( cl_font_t *font );
void CL_SetFontRendermode( cl_font_t *font );
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags );
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags );
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height );
@@ -819,9 +825,12 @@ int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags,
//
void CL_UnloadProgs( void );
qboolean CL_LoadProgs( const char *name );
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num );
void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize );
void CL_ParseFinaleCutscene( sizebuf_t *msg, int level );
void CL_ParseTextMessage( sizebuf_t *msg );
void CL_DrawHUD( int state );
void CL_InitEdicts( int maxclients );
void CL_InitEdicts( void );
void CL_FreeEdicts( void );
void CL_ClearWorld( void );
void CL_DrawCenterPrint( void );
@@ -829,86 +838,64 @@ void CL_ClearSpriteTextures( void );
void CL_CenterPrint( const char *text, float y );
void CL_TextMessageParse( byte *pMemFile, int fileSize );
client_textmessage_t *CL_TextMessageGet( const char *pName );
int pfnDecalIndexFromName( const char *szDecalName );
int pfnIndexFromTrace( struct pmtrace_s *pTrace );
model_t *CL_ModelHandle( int modelindex );
void NetAPI_CancelAllRequests( void );
int CL_FindModelIndex( const char *m );
cl_entity_t *CL_GetLocalPlayer( void );
model_t *CL_LoadClientSprite( const char *filename );
model_t *CL_LoadModel( const char *modelname, int *index );
HSPRITE EXPORT pfnSPR_Load( const char *szPicName );
HSPRITE pfnSPR_LoadExt( const char *szPicName, uint texFlags );
void SPR_AdjustSize( float *x, float *y, float *w, float *h );
void SPR_AdjustTexCoords( float width, float height, float *s1, float *t1, float *s2, float *t2 );
int CL_GetScreenInfo( SCREENINFO *pscrinfo );
void CL_FillRGBA( int x, int y, int width, int height, int r, int g, int b, int a );
void CL_PlayerTrace( float *start, float *end, int traceFlags, int ignore_pe, pmtrace_t *tr );
void CL_PlayerTraceExt( float *start, float *end, int traceFlags, int (*pfnIgnore)( physent_t *pe ), pmtrace_t *tr );
pmtrace_t *PM_CL_TraceLine( float *start, float *end, int flags, int usehull, int ignore_pe );
const char *PM_CL_TraceTexture( int ground, float *vstart, float *vend );
int PM_CL_PointContents( const float *p, int *truecontents );
void CL_SetTraceHull( int hull );
void CL_GetMousePosition( int *mx, int *my ); // TODO: move to input
cl_entity_t* CL_GetViewModel( void );
void pfnGetScreenFade( struct screenfade_s *fade );
physent_t *pfnGetPhysent( int idx );
struct msurface_s *pfnTraceSurface( int ground, float *vstart, float *vend );
movevars_t *pfnGetMoveVars( void );
void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int height );
void CL_DisableScissor( scissor_state_t *scissor );
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
struct cl_entity_s *CL_GetEntityByIndex( int index );
_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;
}
//
// cl_parse.c
//
void CL_ParseSetAngle( sizebuf_t *msg );
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 );
void CL_UpdateUserPings( sizebuf_t *msg );
void CL_ParseParticles( sizebuf_t *msg );
void CL_ParseRestoreSoundPacket( sizebuf_t *msg );
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 );
void CL_ParseMovevars( sizebuf_t *msg );
void CL_ParseResourceRequest( sizebuf_t *msg );
void CL_ParseCustomization( sizebuf_t *msg );
void CL_ParseCrosshairAngle( sizebuf_t *msg );
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_ParseResLocation( sizebuf_t *msg );
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext, const connprotocol_t proto );
void CL_ParseServerMessage( sizebuf_t *msg );
void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message );
void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message );
void CL_LegacyPrecache_f( void );
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 );
void CL_ParseViewEntity( sizebuf_t *msg );
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_BatchResourceRequest( qboolean initialize );
int CL_EstimateNeededResources( void );
//
// cl_parse_48.c
//
void CL_ParseLegacyServerMessage( sizebuf_t *msg );
void CL_LegacyPrecache_f( void );
//
// cl_scrn.c
@@ -916,6 +903,8 @@ void CL_LegacyPrecache_f( void );
void SCR_VidInit( void );
void SCR_TileClear( void );
void SCR_DirtyScreen( void );
void SCR_AddDirtyPoint( int x, int y );
void SCR_InstallParticlePalette( void );
void SCR_EndLoadingPlaque( void );
void SCR_RegisterTextures( void );
void SCR_LoadCreditsFont( void );
@@ -925,7 +914,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
@@ -952,22 +940,25 @@ void CL_InitClientMove( void );
void CL_PredictMovement( qboolean repredicting );
void CL_CheckPredictionError( void );
qboolean CL_IsPredicted( void );
int CL_TruePointContents( const vec3_t p );
int CL_WaterEntity( const float *rgflPos );
cl_entity_t *CL_GetWaterEntity( const float *rgflPos );
int CL_TestLine( const vec3_t start, const vec3_t end, int flags );
pmtrace_t *CL_VisTraceLine( vec3_t start, vec3_t end, int flags );
pmtrace_t CL_TraceLine( vec3_t start, vec3_t end, int flags );
void CL_PushTraceBounds( int hullnum, const float *mins, const float *maxs );
void CL_PopTraceBounds( void );
void CL_MoveSpectatorCamera( void );
void CL_SetLastUpdate( void );
void CL_RedoPrediction( void );
void CL_PushPMStates( void );
void CL_PopPMStates( void );
void CL_SetUpPlayerPrediction( int dopred, int bIncludeLocalClient );
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
@@ -979,17 +970,21 @@ 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 );
qboolean CL_GetMovieSpatialization( struct rawchan_s *ch );
void CL_ProcessPlayerState( int playerindex, entity_state_t *state );
void CL_ComputePlayerOrigin( cl_entity_t *clent );
void CL_ProcessPacket( frame_t *frame );
void CL_MoveThirdpersonCamera( void );
qboolean CL_IsPlayerIndex( int idx );
void CL_SetIdealPitch( void );
void CL_EmitEntities( void );
//
// cl_remap.c
//
remap_info_t *CL_GetRemapInfoForEntity( cl_entity_t *e );
qboolean CL_EntitySetRemapColors( cl_entity_t *e, model_t *mod, int top, int bottom );
void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor, int bottomcolor );
void CL_FreeRemapInfo( remap_info_t *info );
void CL_UpdateRemapInfo( cl_entity_t *ent, int topcolor, int bottomcolor );
void CL_ClearAllRemaps( void );
//
@@ -1006,17 +1001,18 @@ const ref_overview_t *GL_GetOverviewParms( void );
//
void R_StoreEfrags( efrag_t **ppefrag, int framecount );
void R_AddEfrags( cl_entity_t *ent );
//
// cl_tent.c
//
struct particle_s;
int CL_AddEntity( int entityType, cl_entity_t *pEnt );
void CL_WeaponAnim( int iAnim, int body );
void CL_ClearEffects( void );
void CL_ClearEfrags( void );
void CL_TestLights( void );
void CL_FireCustomDecal( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags, float scale );
void CL_DecalShoot( int textureIndex, int entityIndex, int modelIndex, float *pos, int flags );
void CL_PlayerDecal( int playerIndex, int textureIndex, int entityIndex, float *pos );
void R_FreeDeadParticles( struct particle_s **ppparticles );
void CL_AddClientResource( const char *filename, int type );
void CL_AddClientResources( void );
@@ -1038,11 +1034,12 @@ void CL_ReadPointFile_f( void );
void CL_DrawEFX( float time, qboolean fTrans );
void CL_ThinkParticle( double frametime, particle_t *p );
void CL_ReadLineFile_f( void );
void CL_RunLightStyles( void );
//
// console.c
//
extern convar_t con_fontsize;
extern convar_t *con_fontsize;
int Con_Visible( void );
qboolean Con_FixedFont( void );
void Con_VidInit( void );
@@ -1057,22 +1054,27 @@ int Con_UtfProcessChar( int in );
int Con_UtfProcessCharForce( int in );
int Con_UtfMoveLeft( char *str, int pos );
int Con_UtfMoveRight( char *str, int pos, int length );
void Con_DefaultColor( int r, int g, int b, qboolean gameui );
void Con_DefaultColor( int r, int g, int b );
void Con_InvalidateFonts( void );
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 );
void Con_RestoreFont( void );
void Key_Console( int key );
void Key_Message( int key );
void Con_FastClose( void );
void Con_Bottom( void );
void Con_Top( void );
void Con_PageDown( int lines );
void Con_PageUp( int lines );
//
// s_main.c
//
void S_StreamRawSamples( int samples, int rate, int width, int channels, const byte *data );
void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float synctime );
void S_StartBackgroundTrack( const char *intro, const char *loop, int position, qboolean fullpath );
void S_StopBackgroundTrack( void );
@@ -1110,7 +1112,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 );
@@ -1119,6 +1121,11 @@ void UI_ConnectionProgress_Precache( void );
void UI_ConnectionProgress_Connect( const char *server );
void UI_ConnectionProgress_ChangeLevel( void );
void UI_ConnectionProgress_ParseServerInfo( const char *server );
void pfnPIC_Set( HIMAGE hPic, int r, int g, int b, int a );
void pfnPIC_Draw( int x, int y, int width, int height, const wrect_t *prc );
void pfnPIC_DrawTrans( int x, int y, int width, int height, const wrect_t *prc );
void pfnPIC_DrawHoles( int x, int y, int width, int height, const wrect_t *prc );
void pfnPIC_DrawAdditive( int x, int y, int width, int height, const wrect_t *prc );
//
// cl_mobile.c
@@ -1164,7 +1171,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

File diff suppressed because it is too large Load Diff

View File

@@ -1,438 +0,0 @@
/*
gamma.c - gamma routines
Copyright (C) 2011 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 "xash3d_mathlib.h"
#include "enginefeatures.h"
//-----------------------------------------------------------------------------
// Gamma conversion support
//-----------------------------------------------------------------------------
static qboolean gamma_rebuilt;
static byte texgammatable[256];
static uint lightgammatable[1024];
static uint lineargammatable[1024];
static uint screengammatable[1024];
static CVAR_DEFINE( v_direct, "direct", "0.9", 0, "direct studio lighting" );
static CVAR_DEFINE( v_texgamma, "texgamma", "2.0", 0, "texgamma amount" );
static CVAR_DEFINE( v_lightgamma, "lightgamma", "2.5", 0, "lightgamma amount" );
static CVAR_DEFINE( v_brightness, "brightness", "0.0", FCVAR_ARCHIVE, "brightness factor" );
static CVAR_DEFINE( v_gamma, "gamma", "2.5", FCVAR_ARCHIVE, "gamma amount" );
static void BuildGammaTable( const float gamma, const float brightness, const float texgamma, const float lightgamma )
{
float g1, g2, g3;
int i;
if( gamma != 0.0 )
g1 = 1.0 / gamma;
else g1 = 0.4;
g2 = g1 * texgamma;
if( brightness <= 0.0 )
g3 = 0.125;
else if( brightness <= 1.0 )
g3 = 0.125 - brightness * brightness * 0.075;
else
g3 = 0.05;
for( i = 0; i < 256; i++ )
{
double d = pow( i / 255.0, (double)g2 );
int inf = d * 255.0;
texgammatable[i] = bound( 0, inf, 255 );
}
for( i = 0; i < 1024; i++ )
{
double d;
float f = pow( i / 1023.0, (double)lightgamma );
int inf;
if( brightness > 1.0 )
f *= brightness;
if( f <= g3 )
f = ( f / g3 ) * 0.125;
else
f = (( f - g3 ) / ( 1.0 - g3 )) * 0.875 + 0.125;
d = pow( (double)f, (double)g1 ); // do not remove the cast, or tests fail
inf = d * 1023.0;
lightgammatable[i] = bound( 0, inf, 1023 );
// do these calculations in the same loop...
lineargammatable[i] = pow( i / 1023.0, (double)gamma ) * 1023.0;
screengammatable[i] = pow( i / 1023.0, 1.0 / gamma ) * 1023.0;
}
}
static void V_ValidateGammaCvars( void )
{
if( v_gamma.value < 1.8f )
Cvar_DirectSet( &v_gamma, "1.8" );
else if( v_gamma.value > 3.0f )
Cvar_DirectSet( &v_gamma, "3" );
if( v_texgamma.value < 1.8f )
Cvar_DirectSet( &v_texgamma, "1.8" );
else if( v_texgamma.value > 3.0f )
Cvar_DirectSet( &v_texgamma, "3" );
if( v_lightgamma.value < 1.8f )
Cvar_DirectSet( &v_lightgamma, "1.8" );
else if( v_lightgamma.value > 3.0f )
Cvar_DirectSet( &v_lightgamma, "3" );
if( v_brightness.value < 0.0f )
Cvar_DirectSet( &v_brightness, "0" );
else if( v_brightness.value > 3.0f )
Cvar_DirectSet( &v_brightness, "3" );
}
void V_CheckGamma( void )
{
static qboolean dirty = false;
// because these cvars were defined as archive
// but wasn't doing anything useful
// reset them into default values
// this might be removed after a while
if( v_direct.value == 1.0f || v_lightgamma.value == 1.0f )
{
Cvar_DirectSet( &v_direct, "0.9" );
Cvar_DirectSet( &v_lightgamma, "2.5" );
}
if( cls.scrshot_action == scrshot_envshot || cls.scrshot_action == scrshot_skyshot )
{
dirty = true; // force recalculate next normal frame
BuildGammaTable( 1.8f, 0.0f, 2.0f, 2.5f );
if( ref.initialized )
ref.dllFuncs.R_GammaChanged( true );
return;
}
if( dirty || FBitSet( v_texgamma.flags|v_lightgamma.flags|v_brightness.flags|v_gamma.flags, FCVAR_CHANGED ))
{
V_ValidateGammaCvars();
dirty = false;
gamma_rebuilt = true;
BuildGammaTable( v_gamma.value, v_brightness.value, v_texgamma.value, v_lightgamma.value );
// force refdll to recalculate lightmaps
if( ref.initialized )
ref.dllFuncs.R_GammaChanged( false );
}
}
void V_CheckGammaEnd( void )
{
// don't reset changed flag if it was set during frame
// keep it for next frame
if( !gamma_rebuilt )
return;
gamma_rebuilt = false;
// keep the flags until the end of frame so client.dll will catch these changes
if( FBitSet( v_texgamma.flags|v_lightgamma.flags|v_brightness.flags|v_gamma.flags, FCVAR_CHANGED ))
{
ClearBits( v_texgamma.flags, FCVAR_CHANGED );
ClearBits( v_lightgamma.flags, FCVAR_CHANGED );
ClearBits( v_brightness.flags, FCVAR_CHANGED );
ClearBits( v_gamma.flags, FCVAR_CHANGED );
}
}
void V_Init( void )
{
Cvar_RegisterVariable( &v_texgamma );
Cvar_RegisterVariable( &v_lightgamma );
Cvar_RegisterVariable( &v_brightness );
Cvar_RegisterVariable( &v_gamma );
Cvar_RegisterVariable( &v_direct );
// force gamma init
SetBits( v_gamma.flags, FCVAR_CHANGED );
V_CheckGamma();
}
byte TextureToGamma( byte b )
{
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
return b;
return texgammatable[b];
}
byte LightToTexGamma( byte b )
{
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
return b;
// 255 << 2 is 1020, impossible to overflow
return lightgammatable[b << 2] >> 2;
}
uint LightToTexGammaEx( uint b )
{
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
return b;
if( unlikely( b > ARRAYSIZE( lightgammatable )))
return 0;
return lightgammatable[b];
}
uint ScreenGammaTable( uint b )
{
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
return b;
if( unlikely( b > ARRAYSIZE( screengammatable )))
return 0;
return screengammatable[b];
}
uint LinearGammaTable( uint b )
{
if( FBitSet( host.features, ENGINE_LINEAR_GAMMA_SPACE ))
return b;
if( unlikely( b > ARRAYSIZE( lineargammatable )))
return 0;
return lineargammatable[b];
}
#if XASH_ENGINE_TESTS
#include "tests.h"
typedef struct precomputed_gamma_tables_s
{
float gamma;
float brightness;
float texgamma;
float lightgamma;
byte texgammatable[256];
int lightgammatable[1024];
int lineargammatable[1024];
int screengammatable[1024];
} precomputed_gamma_tables_t;
// put at the end of the file, to not confuse Qt Creator's parser
precomputed_gamma_tables_t *Test_GetGammaTables( int i );
static void Test_PrecomputedGammaTables( void )
{
precomputed_gamma_tables_t *data;
int i = 0;
while(( data = Test_GetGammaTables( i )))
{
int j;
BuildGammaTable( data->gamma, data->brightness, data->texgamma, data->lightgamma );
for( j = 0; j < 1024; j++ )
{
if( j < 256 )
{
TASSERT_EQi( texgammatable[j], data->texgammatable[j] );
}
TASSERT_EQi( lightgammatable[j], data->lightgammatable[j] );
TASSERT_EQi( lineargammatable[j], data->lineargammatable[j] );
TASSERT_EQi( screengammatable[j], data->screengammatable[j] );
}
i++;
}
}
void Test_RunGamma( void )
{
TRUN( Test_PrecomputedGammaTables() );
}
precomputed_gamma_tables_t *Test_GetGammaTables( int i )
{
static precomputed_gamma_tables_t precomputed_data[] = {
{
.gamma = 2.5,
.brightness = 0.0,
.texgamma = 2.0,
.lightgamma = 2.5,
.texgammatable = {
0, 3, 5, 7, 9, 10, 12, 14, 15, 17, 19, 20, 22, 23, 25, 26, 27, 29, 30, 31, 33, 34, 35, 37, 38, 39, 41, 42, 43, 44, 46, 47, 48, 49, 50, 52, 53, 54, 55, 56, 57, 59, 60, 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 132, 133, 134, 135, 136, 137, 138,
139, 140, 141, 142, 143, 144, 145, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 165, 166, 167, 168, 169, 170, 171, 172, 172, 173, 174, 175, 176, 177, 178, 179, 180, 180, 181, 182, 183, 184, 185,
186, 186, 187, 188, 189, 190, 191, 192, 192, 193, 194, 195, 196, 197, 198, 198, 199, 200, 201, 202, 203, 204, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 214, 214, 215, 216, 217, 218, 219, 219, 220, 221, 222, 223, 224, 224, 225, 226, 227, 228, 229,
229, 230, 231, 232, 233, 233, 234, 235, 236, 237, 238, 238, 239, 240, 241, 242, 242, 243, 244, 245, 246, 246, 247, 248, 249, 250, 250, 251, 252, 253, 254, 255
},
.lightgammatable = {
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 343, 343, 344, 345, 346, 347, 348, 349, 350, 351, 353, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 376, 376, 377, 379, 379, 380, 381, 382, 383,
384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435,
436, 437, 438, 439, 440, 441, 442, 443, 444, 446, 446, 447, 449, 449, 450, 451, 452, 453, 455, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 468, 469, 470, 470, 472, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487,
488, 489, 490, 491, 493, 493, 494, 495, 496, 498, 498, 499, 500, 502, 502, 503, 504, 505, 507, 508, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 520, 521, 521, 522, 523, 524, 525, 526, 527, 528, 530, 530, 531, 532, 533, 534, 536, 536, 537, 538, 539,
540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 552, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 564, 564, 565, 566, 567, 568, 570, 571, 571, 572, 573, 574, 576, 576, 577, 578, 579, 580, 581, 583, 583, 584, 585, 586, 587, 588, 590, 591, 591,
593, 593, 594, 596, 596, 597, 598, 600, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 611, 611, 612, 613, 615, 615, 616, 618, 618, 620, 621, 621, 622, 624, 625, 626, 627, 627, 628, 629, 630, 632, 633, 633, 634, 635, 636, 638, 638, 639, 641, 642, 643, 643,
644, 645, 646, 648, 648, 650, 651, 651, 652, 654, 655, 656, 656, 658, 658, 660, 660, 662, 662, 664, 664, 665, 666, 668, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 682, 682, 683, 684, 685, 686, 687, 688, 690, 690, 691, 692, 693, 695, 696,
696, 697, 698, 699, 700, 701, 702, 703, 705, 706, 706, 707, 708, 709, 710, 711, 712, 713, 715, 716, 716, 717, 718, 719, 721, 721, 722, 724, 724, 725, 727, 727, 728, 729, 730, 731, 733, 733, 734, 735, 736, 737, 738, 740, 740, 741, 743, 744, 744, 745, 747, 747,
748, 749, 750, 752, 753, 753, 755, 755, 757, 757, 758, 759, 760, 761, 762, 764, 764, 766, 766, 767, 769, 770, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 782, 783, 784, 784, 785, 786, 788, 789, 790, 791, 792, 792, 794, 794, 796, 796, 797, 799, 800,
801, 801, 802, 803, 804, 805, 806, 807, 809, 810, 810, 811, 813, 813, 815, 815, 816, 817, 819, 819, 820, 822, 823, 823, 824, 825, 826, 827, 829, 829, 830, 832, 832, 833, 835, 835, 837, 837, 839, 840, 840, 841, 842, 843, 844, 845, 847, 847, 849, 849, 850, 851,
852, 854, 854, 856, 856, 857, 859, 859, 860, 861, 862, 864, 864, 865, 867, 867, 868, 870, 870, 872, 872, 874, 875, 875, 876, 877, 879, 880, 881, 881, 882, 883, 885, 885, 886, 887, 888, 890, 891, 891, 893, 893, 894, 895, 897, 898, 899, 900, 901, 902, 902, 903,
904, 905, 907, 907, 908, 910, 910, 911, 912, 914, 914, 915, 917, 918, 919, 920, 921, 922, 922, 923, 925, 925, 926, 927, 928, 930, 931, 932, 932, 933, 935, 936, 936, 937, 939, 940, 940, 942, 942, 944, 944, 946, 947, 948, 949, 949, 950, 952, 952, 953, 955, 956,
957, 958, 959, 959, 960, 962, 962, 964, 965, 965, 967, 967, 969, 970, 971, 972, 973, 973, 975, 975, 976, 977, 978, 979, 980, 982, 982, 984, 984, 986, 986, 988, 988, 990, 991, 992, 993, 993, 994, 995, 996, 998, 999, 999, 1000, 1002, 1002, 1004, 1005, 1005,
1006, 1007, 1008, 1010, 1011, 1011, 1013, 1014, 1015, 1016, 1017, 1018, 1018, 1019, 1020, 1021, 1023
},
.lineargammatable = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11,
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 25, 25,
25, 25, 26, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 46, 46, 46,
47, 47, 48, 48, 48, 49, 49, 50, 50, 50, 51, 51, 52, 52, 52, 53, 53, 54, 54, 55, 55, 55, 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76,
77, 77, 78, 78, 79, 79, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 86, 86, 87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 92, 93, 94, 94, 95, 95, 96, 97, 97, 98, 99, 99, 100, 100, 101, 102, 102, 103, 104, 104, 105, 105, 106, 107, 107, 108, 109, 109, 110, 111, 111, 112,
113, 113, 114, 115, 115, 116, 117, 117, 118, 119, 119, 120, 121, 122, 122, 123, 124, 124, 125, 126, 126, 127, 128, 129, 129, 130, 131, 132, 132, 133, 134, 134, 135, 136, 137, 137, 138, 139, 140, 140, 141, 142, 143, 144, 144, 145, 146, 147, 147, 148, 149, 150,
151, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 164, 164, 165, 166, 167, 168, 169, 169, 170, 171, 172, 173, 174, 175, 176, 176, 177, 178, 179, 180, 181, 182, 183, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 193, 194,
195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 249, 250, 251, 252, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 265, 266, 267, 268, 269, 270, 271, 272, 274, 275, 276, 277, 278, 279, 280, 282, 283, 284, 285, 286, 287, 289, 290, 291, 292, 293, 294, 296, 297, 298, 299, 300, 302, 303, 304, 305,
306, 308, 309, 310, 311, 312, 314, 315, 316, 317, 319, 320, 321, 322, 324, 325, 326, 327, 329, 330, 331, 333, 334, 335, 336, 338, 339, 340, 342, 343, 344, 345, 347, 348, 349, 351, 352, 353, 355, 356, 357, 359, 360, 361, 363, 364, 365, 367, 368, 369, 371, 372,
373, 375, 376, 378, 379, 380, 382, 383, 384, 386, 387, 389, 390, 391, 393, 394, 396, 397, 399, 400, 401, 403, 404, 406, 407, 409, 410, 411, 413, 414, 416, 417, 419, 420, 422, 423, 425, 426, 428, 429, 431, 432, 434, 435, 437, 438, 440, 441, 443, 444, 446, 447,
449, 450, 452, 453, 455, 456, 458, 459, 461, 462, 464, 466, 467, 469, 470, 472, 473, 475, 477, 478, 480, 481, 483, 485, 486, 488, 489, 491, 493, 494, 496, 497, 499, 501, 502, 504, 506, 507, 509, 511, 512, 514, 515, 517, 519, 520, 522, 524, 525, 527, 529, 531,
532, 534, 536, 537, 539, 541, 542, 544, 546, 548, 549, 551, 553, 554, 556, 558, 560, 561, 563, 565, 567, 568, 570, 572, 574, 575, 577, 579, 581, 583, 584, 586, 588, 590, 592, 593, 595, 597, 599, 601, 602, 604, 606, 608, 610, 612, 613, 615, 617, 619, 621, 623,
625, 626, 628, 630, 632, 634, 636, 638, 639, 641, 643, 645, 647, 649, 651, 653, 655, 657, 659, 660, 662, 664, 666, 668, 670, 672, 674, 676, 678, 680, 682, 684, 686, 688, 690, 692, 694, 696, 698, 700, 702, 704, 706, 708, 710, 712, 714, 716, 718, 720, 722, 724,
726, 728, 730, 732, 734, 736, 738, 740, 742, 744, 746, 748, 750, 753, 755, 757, 759, 761, 763, 765, 767, 769, 771, 773, 776, 778, 780, 782, 784, 786, 788, 791, 793, 795, 797, 799, 801, 803, 806, 808, 810, 812, 814, 816, 819, 821, 823, 825, 827, 830, 832, 834,
836, 839, 841, 843, 845, 847, 850, 852, 854, 856, 859, 861, 863, 865, 868, 870, 872, 874, 877, 879, 881, 884, 886, 888, 890, 893, 895, 897, 900, 902, 904, 907, 909, 911, 914, 916, 918, 921, 923, 925, 928, 930, 932, 935, 937, 940, 942, 944, 947, 949, 952, 954,
956, 959, 961, 964, 966, 968, 971, 973, 976, 978, 981, 983, 985, 988, 990, 993, 995, 998, 1000, 1003, 1005, 1008, 1010, 1013, 1015, 1018, 1020, 1023
},
.screengammatable = {
0, 63, 84, 99, 111, 121, 130, 139, 146, 154, 160, 166, 172, 178, 183, 188, 193, 198, 203, 207, 212, 216, 220, 224, 228, 231, 235, 239, 242, 245, 249, 252, 255, 259, 262, 265, 268, 271, 274, 276, 279, 282, 285, 287, 290, 293, 295, 298, 300, 303, 305, 308,
310, 313, 315, 317, 320, 322, 324, 326, 328, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 363, 365, 367, 369, 370, 372, 374, 376, 378, 379, 381, 383, 385, 386, 388, 390, 392, 393, 395, 397, 398, 400, 401, 403, 405, 406, 408,
409, 411, 413, 414, 416, 417, 419, 420, 422, 423, 425, 426, 428, 429, 431, 432, 434, 435, 436, 438, 439, 441, 442, 444, 445, 446, 448, 449, 450, 452, 453, 455, 456, 457, 459, 460, 461, 463, 464, 465, 466, 468, 469, 470, 472, 473, 474, 475, 477, 478, 479, 480,
482, 483, 484, 485, 487, 488, 489, 490, 491, 493, 494, 495, 496, 497, 499, 500, 501, 502, 503, 504, 505, 507, 508, 509, 510, 511, 512, 513, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539,
540, 541, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 585, 586, 587, 588, 589, 590,
591, 592, 593, 594, 595, 595, 596, 597, 598, 599, 600, 601, 602, 603, 603, 604, 605, 606, 607, 608, 609, 610, 610, 611, 612, 613, 614, 615, 616, 616, 617, 618, 619, 620, 621, 622, 622, 623, 624, 625, 626, 627, 627, 628, 629, 630, 631, 632, 632, 633, 634, 635,
636, 637, 637, 638, 639, 640, 641, 641, 642, 643, 644, 645, 645, 646, 647, 648, 649, 649, 650, 651, 652, 652, 653, 654, 655, 656, 656, 657, 658, 659, 659, 660, 661, 662, 663, 663, 664, 665, 666, 666, 667, 668, 669, 669, 670, 671, 672, 672, 673, 674, 675, 675,
676, 677, 678, 678, 679, 680, 681, 681, 682, 683, 684, 684, 685, 686, 686, 687, 688, 689, 689, 690, 691, 692, 692, 693, 694, 694, 695, 696, 697, 697, 698, 699, 699, 700, 701, 701, 702, 703, 704, 704, 705, 706, 706, 707, 708, 708, 709, 710, 711, 711, 712, 713,
713, 714, 715, 715, 716, 717, 717, 718, 719, 719, 720, 721, 721, 722, 723, 723, 724, 725, 725, 726, 727, 727, 728, 729, 729, 730, 731, 731, 732, 733, 733, 734, 735, 735, 736, 737, 737, 738, 739, 739, 740, 741, 741, 742, 743, 743, 744, 745, 745, 746, 746, 747,
748, 748, 749, 750, 750, 751, 752, 752, 753, 753, 754, 755, 755, 756, 757, 757, 758, 758, 759, 760, 760, 761, 762, 762, 763, 763, 764, 765, 765, 766, 767, 767, 768, 768, 769, 770, 770, 771, 771, 772, 773, 773, 774, 774, 775, 776, 776, 777, 778, 778, 779, 779,
780, 781, 781, 782, 782, 783, 784, 784, 785, 785, 786, 786, 787, 788, 788, 789, 789, 790, 791, 791, 792, 792, 793, 794, 794, 795, 795, 796, 796, 797, 798, 798, 799, 799, 800, 801, 801, 802, 802, 803, 803, 804, 805, 805, 806, 806, 807, 807, 808, 809, 809, 810,
810, 811, 811, 812, 813, 813, 814, 814, 815, 815, 816, 816, 817, 818, 818, 819, 819, 820, 820, 821, 821, 822, 823, 823, 824, 824, 825, 825, 826, 826, 827, 828, 828, 829, 829, 830, 830, 831, 831, 832, 832, 833, 834, 834, 835, 835, 836, 836, 837, 837, 838, 838,
839, 839, 840, 841, 841, 842, 842, 843, 843, 844, 844, 845, 845, 846, 846, 847, 848, 848, 849, 849, 850, 850, 851, 851, 852, 852, 853, 853, 854, 854, 855, 855, 856, 856, 857, 857, 858, 859, 859, 860, 860, 861, 861, 862, 862, 863, 863, 864, 864, 865, 865, 866,
866, 867, 867, 868, 868, 869, 869, 870, 870, 871, 871, 872, 872, 873, 873, 874, 874, 875, 875, 876, 876, 877, 877, 878, 878, 879, 879, 880, 880, 881, 881, 882, 882, 883, 883, 884, 884, 885, 885, 886, 886, 887, 887, 888, 888, 889, 889, 890, 890, 891, 891, 892,
892, 893, 893, 894, 894, 895, 895, 896, 896, 897, 897, 898, 898, 899, 899, 900, 900, 901, 901, 902, 902, 903, 903, 904, 904, 904, 905, 905, 906, 906, 907, 907, 908, 908, 909, 909, 910, 910, 911, 911, 912, 912, 913, 913, 914, 914, 915, 915, 915, 916, 916, 917,
917, 918, 918, 919, 919, 920, 920, 921, 921, 922, 922, 922, 923, 923, 924, 924, 925, 925, 926, 926, 927, 927, 928, 928, 929, 929, 929, 930, 930, 931, 931, 932, 932, 933, 933, 934, 934, 935, 935, 935, 936, 936, 937, 937, 938, 938, 939, 939, 940, 940, 940, 941,
941, 942, 942, 943, 943, 944, 944, 944, 945, 945, 946, 946, 947, 947, 948, 948, 949, 949, 949, 950, 950, 951, 951, 952, 952, 953, 953, 953, 954, 954, 955, 955, 956, 956, 957, 957, 957, 958, 958, 959, 959, 960, 960, 961, 961, 961, 962, 962, 963, 963, 964, 964,
964, 965, 965, 966, 966, 967, 967, 968, 968, 968, 969, 969, 970, 970, 971, 971, 971, 972, 972, 973, 973, 974, 974, 974, 975, 975, 976, 976, 977, 977, 977, 978, 978, 979, 979, 980, 980, 980, 981, 981, 982, 982, 983, 983, 983, 984, 984, 985, 985, 986, 986, 986,
987, 987, 988, 988, 988, 989, 989, 990, 990, 991, 991, 991, 992, 992, 993, 993, 993, 994, 994, 995, 995, 996, 996, 996, 997, 997, 998, 998, 998, 999, 999, 1000, 1000, 1001, 1001, 1001, 1002, 1002, 1003, 1003, 1003, 1004, 1004, 1005, 1005, 1005, 1006, 1006,
1007, 1007, 1008, 1008, 1008, 1009, 1009, 1010, 1010, 1010, 1011, 1011, 1012, 1012, 1012, 1013, 1013, 1014, 1014, 1014, 1015, 1015, 1016, 1016, 1016, 1017, 1017, 1018, 1018, 1018, 1019, 1019, 1020, 1020, 1020, 1021, 1021, 1022, 1022, 1023
},
}, {
.gamma = 2.2,
.brightness = 1.0,
.texgamma = 2.2,
.lightgamma = 2.4,
.texgammatable = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
},
.lightgammatable = {
0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, 52, 53, 55, 56, 57, 58, 60, 61, 62, 63, 65, 66, 67, 69, 70, 71, 72, 74, 75, 76,
78, 79, 80, 81, 83, 84, 85, 87, 88, 89, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 112, 113, 114, 116, 117, 118, 120, 121, 122, 124, 125, 126, 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 147, 148, 149,
151, 152, 153, 155, 156, 157, 159, 160, 162, 163, 164, 166, 167, 168, 170, 171, 173, 174, 175, 177, 178, 179, 181, 182, 184, 185, 186, 188, 189, 191, 192, 193, 195, 196, 198, 199, 200, 202, 203, 204, 206, 207, 209, 210, 211, 213, 214, 216, 217, 219, 220, 221,
223, 224, 226, 227, 228, 230, 231, 233, 234, 235, 237, 238, 240, 241, 243, 244, 245, 247, 248, 250, 251, 252, 254, 255, 257, 258, 260, 261, 262, 264, 265, 267, 268, 270, 271, 272, 274, 275, 277, 278, 280, 281, 282, 284, 285, 287, 288, 290, 291, 293, 294, 295,
297, 298, 300, 301, 303, 304, 306, 307, 308, 310, 311, 313, 314, 316, 317, 319, 320, 321, 323, 324, 326, 327, 329, 330, 332, 333, 335, 336, 337, 339, 340, 342, 343, 345, 346, 348, 349, 351, 352, 354, 355, 356, 358, 359, 361, 362, 364, 365, 367, 368, 370, 371,
373, 374, 376, 377, 378, 380, 381, 383, 384, 386, 387, 389, 390, 392, 393, 395, 396, 397, 398, 398, 399, 399, 400, 401, 401, 402, 402, 403, 403, 404, 404, 405, 406, 406, 407, 407, 408, 408, 409, 410, 410, 411, 411, 412, 413, 413, 414, 414, 415, 416, 416, 417,
417, 418, 419, 419, 420, 420, 421, 422, 422, 423, 423, 424, 425, 425, 426, 427, 427, 428, 428, 429, 430, 430, 431, 432, 432, 433, 433, 434, 435, 435, 436, 437, 437, 438, 439, 439, 440, 441, 441, 442, 443, 443, 444, 445, 445, 446, 447, 447, 448, 449, 449, 450,
451, 451, 452, 453, 453, 454, 455, 455, 456, 457, 457, 458, 459, 459, 460, 461, 461, 462, 463, 464, 464, 465, 466, 466, 467, 468, 468, 469, 470, 471, 471, 472, 473, 473, 474, 475, 476, 476, 477, 478, 478, 479, 480, 481, 481, 482, 483, 483, 484, 485, 486, 486,
487, 488, 489, 489, 490, 491, 492, 492, 493, 494, 495, 495, 496, 497, 498, 498, 499, 500, 501, 501, 502, 503, 504, 504, 505, 506, 507, 507, 508, 509, 510, 510, 511, 512, 513, 513, 514, 515, 516, 517, 517, 518, 519, 520, 520, 521, 522, 523, 524, 524, 525, 526,
527, 527, 528, 529, 530, 531, 531, 532, 533, 534, 535, 535, 536, 537, 538, 538, 539, 540, 541, 542, 542, 543, 544, 545, 546, 546, 547, 548, 549, 550, 550, 551, 552, 553, 554, 555, 555, 556, 557, 558, 559, 559, 560, 561, 562, 563, 564, 564, 565, 566, 567, 568,
568, 569, 570, 571, 572, 573, 573, 574, 575, 576, 577, 578, 578, 579, 580, 581, 582, 583, 583, 584, 585, 586, 587, 588, 588, 589, 590, 591, 592, 593, 593, 594, 595, 596, 597, 598, 599, 599, 600, 601, 602, 603, 604, 605, 605, 606, 607, 608, 609, 610, 611, 611,
612, 613, 614, 615, 616, 617, 617, 618, 619, 620, 621, 622, 623, 623, 624, 625, 626, 627, 628, 629, 629, 630, 631, 632, 633, 634, 635, 636, 636, 637, 638, 639, 640, 641, 642, 643, 643, 644, 645, 646, 647, 648, 649, 650, 651, 651, 652, 653, 654, 655, 656, 657,
658, 658, 659, 660, 661, 662, 663, 664, 665, 666, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 703,
704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 749, 750, 751,
752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 795, 796, 797, 798, 799, 800,
801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850,
851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 900,
901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952,
953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002,
1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1023
},
.lineargammatable = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36,
36, 36, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 42, 42, 42, 43, 43, 44, 44, 44, 45, 45, 46, 46, 46, 47, 47, 48, 48, 48, 49, 49, 50, 50, 51, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, 55, 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 61, 62, 62, 63,
63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 82, 82, 83, 83, 84, 84, 85, 86, 86, 87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 96, 96, 97, 97, 98, 99,
99, 100, 100, 101, 102, 102, 103, 104, 104, 105, 105, 106, 107, 107, 108, 109, 109, 110, 111, 111, 112, 113, 113, 114, 115, 115, 116, 117, 117, 118, 119, 119, 120, 121, 121, 122, 123, 123, 124, 125, 126, 126, 127, 128, 128, 129, 130, 131, 131, 132, 133, 133,
134, 135, 136, 136, 137, 138, 139, 139, 140, 141, 142, 142, 143, 144, 145, 145, 146, 147, 148, 148, 149, 150, 151, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168, 169, 170, 171, 172, 172, 173, 174,
175, 176, 177, 177, 178, 179, 180, 181, 182, 183, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 195, 196, 197, 198, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
222, 223, 224, 225, 226, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
274, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 288, 289, 290, 291, 292, 293, 294, 295, 296, 298, 299, 300, 301, 302, 303, 304, 305, 307, 308, 309, 310, 311, 312, 313, 315, 316, 317, 318, 319, 320, 322, 323, 324, 325, 326, 328, 329, 330, 331, 332,
333, 335, 336, 337, 338, 339, 341, 342, 343, 344, 346, 347, 348, 349, 350, 352, 353, 354, 355, 357, 358, 359, 360, 362, 363, 364, 365, 367, 368, 369, 370, 372, 373, 374, 375, 377, 378, 379, 381, 382, 383, 384, 386, 387, 388, 390, 391, 392, 393, 395, 396, 397,
399, 400, 401, 403, 404, 405, 407, 408, 409, 411, 412, 413, 415, 416, 417, 419, 420, 421, 423, 424, 426, 427, 428, 430, 431, 432, 434, 435, 437, 438, 439, 441, 442, 443, 445, 446, 448, 449, 450, 452, 453, 455, 456, 458, 459, 460, 462, 463, 465, 466, 468, 469,
470, 472, 473, 475, 476, 478, 479, 481, 482, 483, 485, 486, 488, 489, 491, 492, 494, 495, 497, 498, 500, 501, 503, 504, 506, 507, 509, 510, 512, 513, 515, 516, 518, 519, 521, 522, 524, 525, 527, 528, 530, 532, 533, 535, 536, 538, 539, 541, 542, 544, 545, 547,
549, 550, 552, 553, 555, 556, 558, 560, 561, 563, 564, 566, 568, 569, 571, 572, 574, 576, 577, 579, 580, 582, 584, 585, 587, 589, 590, 592, 593, 595, 597, 598, 600, 602, 603, 605, 607, 608, 610, 612, 613, 615, 617, 618, 620, 622, 623, 625, 627, 628, 630, 632,
633, 635, 637, 639, 640, 642, 644, 645, 647, 649, 650, 652, 654, 656, 657, 659, 661, 663, 664, 666, 668, 670, 671, 673, 675, 677, 678, 680, 682, 684, 685, 687, 689, 691, 692, 694, 696, 698, 700, 701, 703, 705, 707, 709, 710, 712, 714, 716, 718, 719, 721, 723,
725, 727, 729, 730, 732, 734, 736, 738, 740, 741, 743, 745, 747, 749, 751, 753, 754, 756, 758, 760, 762, 764, 766, 767, 769, 771, 773, 775, 777, 779, 781, 783, 785, 786, 788, 790, 792, 794, 796, 798, 800, 802, 804, 806, 808, 809, 811, 813, 815, 817, 819, 821,
823, 825, 827, 829, 831, 833, 835, 837, 839, 841, 843, 845, 847, 849, 851, 853, 855, 857, 859, 861, 863, 865, 867, 869, 871, 873, 875, 877, 879, 881, 883, 885, 887, 889, 891, 893, 895, 897, 899, 901, 903, 905, 907, 910, 912, 914, 916, 918, 920, 922, 924, 926,
928, 930, 932, 934, 937, 939, 941, 943, 945, 947, 949, 951, 953, 956, 958, 960, 962, 964, 966, 968, 970, 973, 975, 977, 979, 981, 983, 985, 988, 990, 992, 994, 996, 998, 1001, 1003, 1005, 1007, 1009, 1012, 1014, 1016, 1018, 1020, 1023
},
.screengammatable = {
0, 43, 60, 72, 82, 91, 98, 106, 112, 118, 124, 130, 135, 140, 145, 150, 154, 158, 163, 167, 171, 174, 178, 182, 185, 189, 192, 196, 199, 202, 205, 208, 211, 214, 217, 220, 223, 226, 228, 231, 234, 237, 239, 242, 244, 247, 249, 252, 254, 257, 259, 261,
264, 266, 268, 270, 273, 275, 277, 279, 281, 283, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 311, 313, 315, 317, 319, 321, 323, 324, 326, 328, 330, 331, 333, 335, 337, 338, 340, 342, 343, 345, 347, 348, 350, 352, 353, 355, 357, 358, 360,
361, 363, 365, 366, 368, 369, 371, 372, 374, 375, 377, 378, 380, 381, 383, 384, 386, 387, 389, 390, 392, 393, 394, 396, 397, 399, 400, 401, 403, 404, 406, 407, 408, 410, 411, 412, 414, 415, 416, 418, 419, 420, 422, 423, 424, 426, 427, 428, 430, 431, 432, 433,
435, 436, 437, 438, 440, 441, 442, 443, 445, 446, 447, 448, 450, 451, 452, 453, 454, 456, 457, 458, 459, 460, 462, 463, 464, 465, 466, 467, 469, 470, 471, 472, 473, 474, 475, 477, 478, 479, 480, 481, 482, 483, 484, 486, 487, 488, 489, 490, 491, 492, 493, 494,
495, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 545, 546, 547,
548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 583, 584, 585, 586, 587, 588, 589, 590, 591, 591, 592, 593, 594, 595,
596, 597, 598, 598, 599, 600, 601, 602, 603, 604, 604, 605, 606, 607, 608, 609, 609, 610, 611, 612, 613, 614, 615, 615, 616, 617, 618, 619, 620, 620, 621, 622, 623, 624, 624, 625, 626, 627, 628, 629, 629, 630, 631, 632, 633, 633, 634, 635, 636, 637, 637, 638,
639, 640, 641, 641, 642, 643, 644, 645, 645, 646, 647, 648, 649, 649, 650, 651, 652, 652, 653, 654, 655, 656, 656, 657, 658, 659, 659, 660, 661, 662, 663, 663, 664, 665, 666, 666, 667, 668, 669, 669, 670, 671, 672, 672, 673, 674, 675, 675, 676, 677, 678, 678,
679, 680, 681, 681, 682, 683, 684, 684, 685, 686, 686, 687, 688, 689, 689, 690, 691, 692, 692, 693, 694, 694, 695, 696, 697, 697, 698, 699, 700, 700, 701, 702, 702, 703, 704, 705, 705, 706, 707, 707, 708, 709, 709, 710, 711, 712, 712, 713, 714, 714, 715, 716,
716, 717, 718, 719, 719, 720, 721, 721, 722, 723, 723, 724, 725, 725, 726, 727, 728, 728, 729, 730, 730, 731, 732, 732, 733, 734, 734, 735, 736, 736, 737, 738, 738, 739, 740, 740, 741, 742, 742, 743, 744, 744, 745, 746, 746, 747, 748, 748, 749, 750, 750, 751,
752, 752, 753, 754, 754, 755, 756, 756, 757, 758, 758, 759, 759, 760, 761, 761, 762, 763, 763, 764, 765, 765, 766, 767, 767, 768, 769, 769, 770, 770, 771, 772, 772, 773, 774, 774, 775, 776, 776, 777, 777, 778, 779, 779, 780, 781, 781, 782, 782, 783, 784, 784,
785, 786, 786, 787, 787, 788, 789, 789, 790, 791, 791, 792, 792, 793, 794, 794, 795, 795, 796, 797, 797, 798, 799, 799, 800, 800, 801, 802, 802, 803, 803, 804, 805, 805, 806, 806, 807, 808, 808, 809, 809, 810, 811, 811, 812, 812, 813, 814, 814, 815, 815, 816,
817, 817, 818, 818, 819, 820, 820, 821, 821, 822, 823, 823, 824, 824, 825, 825, 826, 827, 827, 828, 828, 829, 830, 830, 831, 831, 832, 833, 833, 834, 834, 835, 835, 836, 837, 837, 838, 838, 839, 839, 840, 841, 841, 842, 842, 843, 843, 844, 845, 845, 846, 846,
847, 847, 848, 849, 849, 850, 850, 851, 851, 852, 853, 853, 854, 854, 855, 855, 856, 857, 857, 858, 858, 859, 859, 860, 860, 861, 862, 862, 863, 863, 864, 864, 865, 865, 866, 867, 867, 868, 868, 869, 869, 870, 870, 871, 872, 872, 873, 873, 874, 874, 875, 875,
876, 876, 877, 878, 878, 879, 879, 880, 880, 881, 881, 882, 882, 883, 884, 884, 885, 885, 886, 886, 887, 887, 888, 888, 889, 889, 890, 891, 891, 892, 892, 893, 893, 894, 894, 895, 895, 896, 896, 897, 898, 898, 899, 899, 900, 900, 901, 901, 902, 902, 903, 903,
904, 904, 905, 905, 906, 906, 907, 908, 908, 909, 909, 910, 910, 911, 911, 912, 912, 913, 913, 914, 914, 915, 915, 916, 916, 917, 917, 918, 918, 919, 920, 920, 921, 921, 922, 922, 923, 923, 924, 924, 925, 925, 926, 926, 927, 927, 928, 928, 929, 929, 930, 930,
931, 931, 932, 932, 933, 933, 934, 934, 935, 935, 936, 936, 937, 937, 938, 938, 939, 939, 940, 940, 941, 941, 942, 942, 943, 943, 944, 944, 945, 945, 946, 946, 947, 947, 948, 948, 949, 949, 950, 950, 951, 951, 952, 952, 953, 953, 954, 954, 955, 955, 956, 956,
957, 957, 958, 958, 959, 959, 960, 960, 961, 961, 962, 962, 963, 963, 964, 964, 965, 965, 966, 966, 967, 967, 968, 968, 969, 969, 969, 970, 970, 971, 971, 972, 972, 973, 973, 974, 974, 975, 975, 976, 976, 977, 977, 978, 978, 979, 979, 980, 980, 981, 981, 982,
982, 982, 983, 983, 984, 984, 985, 985, 986, 986, 987, 987, 988, 988, 989, 989, 990, 990, 991, 991, 991, 992, 992, 993, 993, 994, 994, 995, 995, 996, 996, 997, 997, 998, 998, 999, 999, 999, 1000, 1000, 1001, 1001, 1002, 1002, 1003, 1003, 1004, 1004, 1005,
1005, 1006, 1006, 1006, 1007, 1007, 1008, 1008, 1009, 1009, 1010, 1010, 1011, 1011, 1012, 1012, 1012, 1013, 1013, 1014, 1014, 1015, 1015, 1016, 1016, 1017, 1017, 1017, 1018, 1018, 1019, 1019, 1020, 1020, 1021, 1021, 1022, 1022, 1023
},
}
};
if( i < 0 || i >= ARRAYSIZE( precomputed_data ))
return NULL;
return &precomputed_data[i];
}
#endif

View File

@@ -45,24 +45,22 @@ static struct joy_axis_s
} joyaxis[MAX_AXES] = { 0 };
static byte currentbinding; // add posibility to remap keys, to place it in joykeys[]
static qboolean joy_initialized;
static CVAR_DEFINE_AUTO( joy_pitch, "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick pitch sensitivity" );
static CVAR_DEFINE_AUTO( joy_yaw, "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick yaw sensitivity" );
static CVAR_DEFINE_AUTO( joy_side, "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick side sensitivity. Values from -1.0 to 1.0" );
static CVAR_DEFINE_AUTO( joy_forward, "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick forward sensitivity. Values from -1.0 to 1.0" );
static CVAR_DEFINE_AUTO( joy_lt_threshold, "16384", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "left trigger threshold. Value from 0 to 32767");
static CVAR_DEFINE_AUTO( joy_rt_threshold, "16384", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "right trigger threshold. Value from 0 to 32767" );
static CVAR_DEFINE_AUTO( joy_side_key_threshold, "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis key event emit threshold. Value from 0 to 32767" );
static CVAR_DEFINE_AUTO( joy_forward_key_threshold, "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis key event emit threshold. Value from 0 to 32767");
static CVAR_DEFINE_AUTO( joy_side_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis deadzone. Value from 0 to 32767" );
static CVAR_DEFINE_AUTO( joy_forward_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis deadzone. Value from 0 to 32767");
static CVAR_DEFINE_AUTO( joy_pitch_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "pitch axis deadzone. Value from 0 to 32767");
static CVAR_DEFINE_AUTO( joy_yaw_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "yaw axis deadzone. Value from 0 to 32767" );
static CVAR_DEFINE_AUTO( joy_axis_binding, "sfpyrl", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "axis hardware id to engine inner axis binding, "
"s - side, f - forward, y - yaw, p - pitch, r - left trigger, l - right trigger" );
static CVAR_DEFINE_AUTO( joy_found, "0", FCVAR_READ_ONLY, "is joystick is connected" );
static CVAR_DEFINE_AUTO( joy_index, "0", FCVAR_READ_ONLY, "current active joystick" );
CVAR_DEFINE_AUTO( joy_enable, "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable joystick" );
convar_t *joy_enable;
static convar_t *joy_pitch;
static convar_t *joy_yaw;
static convar_t *joy_forward;
static convar_t *joy_side;
static convar_t *joy_found;
static convar_t *joy_index;
static convar_t *joy_lt_threshold;
static convar_t *joy_rt_threshold;
static convar_t *joy_side_deadzone;
static convar_t *joy_forward_deadzone;
static convar_t *joy_side_key_threshold;
static convar_t *joy_forward_key_threshold;
static convar_t *joy_pitch_deadzone;
static convar_t *joy_yaw_deadzone;
static convar_t *joy_axis_binding;
/*
============
@@ -71,7 +69,7 @@ Joy_IsActive
*/
qboolean Joy_IsActive( void )
{
return joy_found.value && joy_enable.value;
return joy_found->value && joy_enable->value;
}
/*
@@ -96,7 +94,7 @@ void Joy_HatMotionEvent( byte hat, byte value )
};
int i;
if( !joy_found.value )
if( !joy_found->value )
return;
for( i = 0; i < ARRAYSIZE( keys ); i++ )
@@ -127,14 +125,14 @@ static void Joy_ProcessTrigger( const engineAxis_t engineAxis, short value )
{
case JOY_AXIS_RT:
trigButton = K_JOY2;
trigThreshold = joy_rt_threshold.value;
trigThreshold = joy_rt_threshold->value;
break;
case JOY_AXIS_LT:
trigButton = K_JOY1;
trigThreshold = joy_lt_threshold.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;
}
@@ -161,12 +159,12 @@ static int Joy_GetHatValueForAxis( const engineAxis_t engineAxis )
switch( engineAxis )
{
case JOY_AXIS_SIDE:
threshold = joy_side_key_threshold.value;
threshold = joy_side_key_threshold->value;
negative = JOY_HAT_LEFT;
positive = JOY_HAT_RIGHT;
break;
case JOY_AXIS_FWD:
threshold = joy_side_key_threshold.value;
threshold = joy_side_key_threshold->value;
negative = JOY_HAT_UP;
positive = JOY_HAT_DOWN;
break;
@@ -200,12 +198,12 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
switch( engineAxis )
{
case JOY_AXIS_FWD: deadzone = joy_forward_deadzone.value; break;
case JOY_AXIS_SIDE: deadzone = joy_side_deadzone.value; break;
case JOY_AXIS_PITCH: deadzone = joy_pitch_deadzone.value; break;
case JOY_AXIS_YAW: deadzone = joy_yaw_deadzone.value; break;
case JOY_AXIS_FWD: deadzone = joy_forward_deadzone->value; break;
case JOY_AXIS_SIDE: deadzone = joy_side_deadzone->value; break;
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 +216,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;
@@ -238,7 +236,7 @@ Axis events
*/
void Joy_AxisMotionEvent( byte axis, short value )
{
if( !joy_found.value )
if( !joy_found->value )
return;
if( axis >= MAX_AXES )
@@ -273,7 +271,7 @@ Trackball events. UNDONE
*/
void Joy_BallMotionEvent( byte ball, short xrel, short yrel )
{
//if( !joy_found.value )
//if( !joy_found->value )
// return;
}
@@ -286,7 +284,7 @@ Button events
*/
void Joy_ButtonEvent( byte button, byte down )
{
if( !joy_found.value )
if( !joy_found->value )
return;
// generic game button code.
@@ -311,7 +309,7 @@ Called when joystick is removed. For future expansion
*/
void Joy_RemoveEvent( void )
{
if( joy_found.value )
if( joy_found->value )
Cvar_FullSet( "joy_found", "0", FCVAR_READ_ONLY );
}
@@ -324,7 +322,7 @@ Called when joystick is removed. For future expansion
*/
void Joy_AddEvent( void )
{
if( joy_enable.value && !joy_found.value )
if( joy_enable->value && !joy_found->value )
Cvar_FullSet( "joy_found", "1", FCVAR_READ_ONLY );
}
@@ -340,9 +338,9 @@ void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw )
if( !Joy_IsActive() )
return;
if( FBitSet( joy_axis_binding.flags, FCVAR_CHANGED ) )
if( FBitSet( joy_axis_binding->flags, FCVAR_CHANGED ) )
{
const char *bind = joy_axis_binding.string;
const char *bind = joy_axis_binding->string;
size_t i;
for( i = 0; bind[i]; i++ )
@@ -359,18 +357,18 @@ void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw )
}
}
ClearBits( joy_axis_binding.flags, FCVAR_CHANGED );
ClearBits( joy_axis_binding->flags, FCVAR_CHANGED );
}
*fw -= joy_forward.value * (float)joyaxis[JOY_AXIS_FWD ].val/(float)SHRT_MAX; // must be form -1.0 to 1.0
*side += joy_side.value * (float)joyaxis[JOY_AXIS_SIDE].val/(float)SHRT_MAX;
*fw -= joy_forward->value * (float)joyaxis[JOY_AXIS_FWD ].val/(float)SHRT_MAX; // must be form -1.0 to 1.0
*side += joy_side->value * (float)joyaxis[JOY_AXIS_SIDE].val/(float)SHRT_MAX;
#if !defined(XASH_SDL)
*dpitch += joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime; // abs axis rotate is frametime related
*dyaw -= joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
*dpitch += joy_pitch->value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime; // abs axis rotate is frametime related
*dyaw -= joy_yaw->value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
#else
// HACKHACK: SDL have inverted look axis.
*dpitch -= joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime;
*dyaw += joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
*dpitch -= joy_pitch->value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime;
*dyaw += joy_yaw->value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
#endif
}
@@ -383,31 +381,32 @@ Main init procedure
*/
void Joy_Init( void )
{
Cvar_RegisterVariable( &joy_pitch );
Cvar_RegisterVariable( &joy_yaw );
Cvar_RegisterVariable( &joy_side );
Cvar_RegisterVariable( &joy_forward );
joy_pitch = Cvar_Get( "joy_pitch", "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick pitch sensitivity" );
joy_yaw = Cvar_Get( "joy_yaw", "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick yaw sensitivity" );
joy_side = Cvar_Get( "joy_side", "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick side sensitivity. Values from -1.0 to 1.0" );
joy_forward = Cvar_Get( "joy_forward", "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick forward sensitivity. Values from -1.0 to 1.0" );
Cvar_RegisterVariable( &joy_lt_threshold );
Cvar_RegisterVariable( &joy_rt_threshold );
joy_lt_threshold = Cvar_Get( "joy_lt_threshold", "16384", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "left trigger threshold. Value from 0 to 32767");
joy_rt_threshold = Cvar_Get( "joy_rt_threshold", "16384", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "right trigger threshold. Value from 0 to 32767" );
// emit a key event at 75% axis move
Cvar_RegisterVariable( &joy_side_key_threshold );
Cvar_RegisterVariable( &joy_forward_key_threshold );
joy_side_key_threshold = Cvar_Get( "joy_side_key_threshold", "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis key event emit threshold. Value from 0 to 32767" );
joy_forward_key_threshold = Cvar_Get( "joy_forward_key_threshold", "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis key event emit threshold. Value from 0 to 32767");
// by default, we rely on deadzone detection come from system, but some glitchy devices report false deadzones
Cvar_RegisterVariable( &joy_side_deadzone );
Cvar_RegisterVariable( &joy_forward_deadzone );
Cvar_RegisterVariable( &joy_pitch_deadzone );
Cvar_RegisterVariable( &joy_yaw_deadzone );
joy_side_deadzone = Cvar_Get( "joy_side_deadzone", DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis deadzone. Value from 0 to 32767" );
joy_forward_deadzone = Cvar_Get( "joy_forward_deadzone", DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis deadzone. Value from 0 to 32767");
joy_pitch_deadzone = Cvar_Get( "joy_pitch_deadzone", DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "pitch axis deadzone. Value from 0 to 32767");
joy_yaw_deadzone = Cvar_Get( "joy_yaw_deadzone", DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "yaw axis deadzone. Value from 0 to 32767" );
Cvar_RegisterVariable( &joy_axis_binding );
Cvar_RegisterVariable( &joy_found );
joy_axis_binding = Cvar_Get( "joy_axis_binding", "sfpyrl", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "axis hardware id to engine inner axis binding, "
"s - side, f - forward, y - yaw, p - pitch, r - left trigger, l - right trigger" );
joy_found = Cvar_Get( "joy_found", "0", FCVAR_READ_ONLY, "is joystick is connected" );
// we doesn't loaded config.cfg yet, so this cvar is not archive.
// change by +set joy_index in cmdline
Cvar_RegisterVariable( &joy_index );
joy_index = Cvar_Get( "joy_index", "0", FCVAR_READ_ONLY, "current active joystick" );
Cvar_RegisterVariable( &joy_enable );
joy_enable = Cvar_Get( "joy_enable", "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable joystick" );
// renamed from -nojoy to -noenginejoy to not conflict with
// client.dll's joystick support
@@ -417,7 +416,7 @@ void Joy_Init( void )
return;
}
Cvar_FullSet( "joy_found", va( "%d", Platform_JoyInit( joy_index.value )), FCVAR_READ_ONLY );
Cvar_FullSet( "joy_found", va( "%d", Platform_JoyInit( joy_index->value )), FCVAR_READ_ONLY );
joy_initialized = true;
}

View File

@@ -132,8 +132,6 @@ static struct touch_s
int whitetexture;
int joytexture; // touch indicator
qboolean configchanged;
float actual_aspect_ratio; // maximum aspect ratio from launch, or aspect ratio when entering editor
float config_aspect_ratio; // aspect ratio set by command from config or after entering editor
} touch;
// private to the engine flags
@@ -142,27 +140,28 @@ static struct touch_s
touchdefaultbutton_t g_DefaultButtons[256];
int g_LastDefaultButton;
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" );
static CVAR_DEFINE_AUTO( touch_yaw, "120", FCVAR_FILTERABLE, "touch yaw sensitivity" );
static CVAR_DEFINE_AUTO( touch_nonlinear_look, "0", FCVAR_FILTERABLE, "enable nonlinear touch look" );
static CVAR_DEFINE_AUTO( touch_pow_factor, "1.3", FCVAR_FILTERABLE, "set > 1 to enable" );
static CVAR_DEFINE_AUTO( touch_pow_mult, "400.0", FCVAR_FILTERABLE, "power multiplier, usually 200-1000" );
static CVAR_DEFINE_AUTO( touch_exp_mult, "0", FCVAR_FILTERABLE, "exponent multiplier, usually 20-200, 0 to disable" );
static CVAR_DEFINE_AUTO( touch_grid_count, "50", FCVAR_FILTERABLE, "touch grid count" );
static CVAR_DEFINE_AUTO( touch_grid_enable, "1", FCVAR_FILTERABLE, "enable touch grid" );
static CVAR_DEFINE_AUTO( touch_config_file, "touch.cfg", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "current touch profile file" );
static CVAR_DEFINE_AUTO( touch_precise_amount, "0.5", FCVAR_FILTERABLE, "sensitivity multiplier for precise-look" );
static CVAR_DEFINE_AUTO( touch_highlight_r, "1.0", 0, "highlight r color" );
static CVAR_DEFINE_AUTO( touch_highlight_g, "1.0", 0, "highlight g color" );
static CVAR_DEFINE_AUTO( touch_highlight_b, "1.0", 0, "highlight b color" );
static CVAR_DEFINE_AUTO( touch_highlight_a, "1.0", 0, "highlight alpha" );
static CVAR_DEFINE_AUTO( touch_dpad_radius, "1.0", FCVAR_FILTERABLE, "dpad radius multiplier" );
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");
convar_t *touch_pitch;
convar_t *touch_yaw;
convar_t *touch_forwardzone;
convar_t *touch_sidezone;
convar_t *touch_nonlinear_look;
convar_t *touch_pow_mult;
convar_t *touch_pow_factor;
convar_t *touch_exp_mult;
convar_t *touch_grid_enable;
convar_t *touch_grid_count;
convar_t *touch_config_file;
convar_t *touch_in_menu;
convar_t *touch_joy_radius;
convar_t *touch_dpad_radius;
convar_t *touch_move_indicator;
convar_t *touch_highlight_r;
convar_t *touch_highlight_g;
convar_t *touch_highlight_b;
convar_t *touch_highlight_a;
convar_t *touch_precise_amount;
convar_t *touch_joy_texture;
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" );
@@ -170,42 +169,13 @@ CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate
#define B(x) (button->x)
#define SCR_W ((float)refState.width)
#define SCR_H ((float)refState.height)
#define TO_SCRN_Y(x) (refState.width * (x) * Touch_AspectRatio())
#define TO_SCRN_Y(x) (refState.height * (x))
#define TO_SCRN_X(x) (refState.width * (x))
static void IN_TouchCheckCoords( float *x1, float *y1, float *x2, float *y2 );
static void IN_TouchEditClear( void );
static void Touch_InitConfig( void );
void Touch_NotifyResize( void )
{
if( refState.width && refState.height && ( !touch.configchanged || !touch.actual_aspect_ratio ))
{
float aspect_ratio = SCR_H/SCR_W;
if( aspect_ratio < 0.99 && aspect_ratio > touch.actual_aspect_ratio )
touch.actual_aspect_ratio = aspect_ratio;
}
}
static inline float Touch_AspectRatio( void )
{
if( touch.config_aspect_ratio )
return touch.config_aspect_ratio;
else if( touch.actual_aspect_ratio )
return touch.actual_aspect_ratio;
else if( refState.width && refState.height )
return SCR_H/SCR_W;
else
return 9.0f / 16.0f;
}
static void Touch_ConfigAspectRatio_f( void )
{
touch.config_aspect_ratio = Q_atof( Cmd_Argv( 1 ));
}
/*
==========================
Touch_ExportButtonToConfig
@@ -237,7 +207,7 @@ static inline int Touch_ExportButtonToConfig( file_t *f, touch_button_t *button,
if( keepAspect )
{
float aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(Touch_AspectRatio()) );
float aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(SCR_H/SCR_W) );
FS_Printf( f, " %f\n", aspect );
}
else FS_Printf( f, "\n" );
@@ -252,7 +222,7 @@ Touch_DumpConfig
Dump config to file
=================
*/
static qboolean Touch_DumpConfig( const char *name, const char *profilename )
qboolean Touch_DumpConfig( const char *name, const char *profilename )
{
file_t *f;
touch_button_t *button;
@@ -272,38 +242,36 @@ static qboolean Touch_DumpConfig( const char *name, const char *profilename )
FS_Printf( f, "\ntouch_config_file \"%s\"\n", profilename );
FS_Printf( f, "\n// touch cvars\n" );
FS_Printf( f, "\n// sensitivity settings\n" );
FS_Printf( f, "touch_pitch \"%f\"\n", touch_pitch.value );
FS_Printf( f, "touch_yaw \"%f\"\n", touch_yaw.value );
FS_Printf( f, "touch_forwardzone \"%f\"\n", touch_forwardzone.value );
FS_Printf( f, "touch_sidezone \"%f\"\n", touch_sidezone.value );
FS_Printf( f, "touch_nonlinear_look \"%d\"\n", touch_nonlinear_look.value ? 1 : 0 );
FS_Printf( f, "touch_pow_factor \"%f\"\n", touch_pow_factor.value );
FS_Printf( f, "touch_pow_mult \"%f\"\n", touch_pow_mult.value );
FS_Printf( f, "touch_exp_mult \"%f\"\n", touch_exp_mult.value );
FS_Printf( f, "touch_pitch \"%f\"\n", touch_pitch->value );
FS_Printf( f, "touch_yaw \"%f\"\n", touch_yaw->value );
FS_Printf( f, "touch_forwardzone \"%f\"\n", touch_forwardzone->value );
FS_Printf( f, "touch_sidezone \"%f\"\n", touch_sidezone->value );
FS_Printf( f, "touch_nonlinear_look \"%d\"\n", CVAR_TO_BOOL(touch_nonlinear_look));
FS_Printf( f, "touch_pow_factor \"%f\"\n", touch_pow_factor->value );
FS_Printf( f, "touch_pow_mult \"%f\"\n", touch_pow_mult->value );
FS_Printf( f, "touch_exp_mult \"%f\"\n", touch_exp_mult->value );
FS_Printf( f, "\n// grid settings\n" );
FS_Printf( f, "touch_grid_count \"%d\"\n", (int)touch_grid_count.value );
FS_Printf( f, "touch_grid_enable \"%d\"\n", touch_grid_enable.value ? 1 : 0 );
FS_Printf( f, "touch_grid_count \"%d\"\n", (int)touch_grid_count->value );
FS_Printf( f, "touch_grid_enable \"%d\"\n", CVAR_TO_BOOL(touch_grid_enable));
FS_Printf( f, "\n// global overstroke (width, r, g, b, a)\n" );
FS_Printf( f, "touch_set_stroke %d %d %d %d %d\n", touch.swidth, touch.scolor[0], touch.scolor[1], touch.scolor[2], touch.scolor[3] );
FS_Printf( f, "\n// highlight when pressed\n" );
FS_Printf( f, "touch_highlight_r \"%f\"\n", touch_highlight_r.value );
FS_Printf( f, "touch_highlight_g \"%f\"\n", touch_highlight_g.value );
FS_Printf( f, "touch_highlight_b \"%f\"\n", touch_highlight_b.value );
FS_Printf( f, "touch_highlight_a \"%f\"\n", touch_highlight_a.value );
FS_Printf( f, "touch_highlight_r \"%f\"\n", touch_highlight_r->value );
FS_Printf( f, "touch_highlight_g \"%f\"\n", touch_highlight_g->value );
FS_Printf( f, "touch_highlight_b \"%f\"\n", touch_highlight_b->value );
FS_Printf( f, "touch_highlight_a \"%f\"\n", touch_highlight_a->value );
FS_Printf( f, "\n// _joy and _dpad options\n" );
FS_Printf( f, "touch_dpad_radius \"%f\"\n", touch_dpad_radius.value );
FS_Printf( f, "touch_joy_radius \"%f\"\n", touch_joy_radius.value );
FS_Printf( f, "touch_dpad_radius \"%f\"\n", touch_dpad_radius->value );
FS_Printf( f, "touch_joy_radius \"%f\"\n", touch_joy_radius->value );
FS_Printf( f, "\n// how much slowdown when Precise Look button pressed\n" );
FS_Printf( f, "touch_precise_amount \"%f\"\n", touch_precise_amount.value );
FS_Printf( f, "touch_precise_amount \"%f\"\n", touch_precise_amount->value );
FS_Printf( f, "\n// enable/disable move indicator\n" );
FS_Printf( f, "touch_move_indicator \"%f\"\n", touch_move_indicator.value );
FS_Printf( f, "touch_move_indicator \"%f\"\n", touch_move_indicator->value );
FS_Printf( f, "\n// reset menu state when execing config\n" );
FS_Printf( f, "touch_setclientonly 0\n" );
FS_Printf( f, "\n// touch buttons\n" );
FS_Printf( f, "touch_removeall\n" );
FS_Printf( f, "touch_aspectratio %f\n", Touch_AspectRatio());
for( button = touch.list_user.first; button; button = button->next )
{
@@ -333,18 +301,18 @@ 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 );
Q_snprintf( newconfigfile, sizeof( newconfigfile ), "%s.new", touch_config_file->string );
Q_snprintf( oldconfigfile, sizeof( oldconfigfile ), "%s.bak", touch_config_file->string );
if( Touch_DumpConfig( newconfigfile, touch_config_file.string ))
if( Touch_DumpConfig( newconfigfile, touch_config_file->string ))
{
FS_Delete( oldconfigfile );
FS_Rename( touch_config_file.string, oldconfigfile );
FS_Rename( touch_config_file->string, oldconfigfile );
FS_Delete( touch_config_file.string );
FS_Rename( newconfigfile, touch_config_file.string );
FS_Delete( touch_config_file->string );
FS_Rename( newconfigfile, touch_config_file->string );
}
}
@@ -409,7 +377,7 @@ static void Touch_GenerateCode_f( void )
if( FBitSet( flags, TOUCH_FL_DEF_HIDE ))
SetBits( flags, TOUCH_FL_HIDE );
aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(Touch_AspectRatio()) );
aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(SCR_H/SCR_W) );
if( memcmp( &c, &B(color), sizeof( rgba_t ) ) )
{
Con_Printf( "unsigned char color[] = { %d, %d, %d, %d };\n", B(color[0]), B(color[1]), B(color[2]), B(color[3]) );
@@ -425,7 +393,7 @@ static void Touch_RoundAll_f( void )
{
touch_button_t *button;
if( !touch_grid_enable.value )
if( !touch_grid_enable->value )
return;
for( button = touch.list_user.first; button; button = button->next )
@@ -582,7 +550,6 @@ static void Touch_RemoveAll_f( void )
{
IN_TouchEditClear();
Touch_ClearList( &touch.list_user );
touch.config_aspect_ratio = 0.0f;
}
static void Touch_SetColor( touchbuttonlist_t *list, const char *name, byte *color )
@@ -760,8 +727,6 @@ static void Touch_SetCommand_f( void )
Con_Printf( S_USAGE "touch_setcommand <name> <command>\n" );
}
static void Touch_LoadDefaults_f( void );
static void Touch_ReloadConfig_f( void )
{
touch.state = state_none;
@@ -771,15 +736,8 @@ static void Touch_ReloadConfig_f( void )
touch.selection->finger = -1;
touch.edit = touch.selection = NULL;
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
if( FS_FileExists( touch_config_file.string, true ) )
{
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file.string );
}
else
{
Touch_LoadDefaults_f();
touch.configchanged = true;
}
Cbuf_AddTextf( "exec %s\n", touch_config_file->string );
}
static touch_button_t *Touch_AddButton( touchbuttonlist_t *list,
@@ -827,7 +785,7 @@ void Touch_AddClientButton( const char *name, const char *texture, const char *c
IN_TouchCheckCoords( &x1, &y1, &x2, &y2 );
if( round == round_aspect )
{
y2 = y1 + ( x2 - x1 ) / (Touch_AspectRatio()) * aspect;
y2 = y1 + ( x2 - x1 ) * (SCR_W/SCR_H) * aspect;
}
button = Touch_AddButton( &touch.list_user, name, texture, command, x1, y1, x2, y2, color, true );
button->flags |= flags | TOUCH_FL_CLIENT | TOUCH_FL_NOEDIT;
@@ -852,7 +810,7 @@ static void Touch_LoadDefaults_f( void )
if( g_DefaultButtons[i].texturefile[0] == '#' )
y2 = y1 + ( (float)clgame.scrInfo.iCharHeight / (float)clgame.scrInfo.iHeight ) * g_DefaultButtons[i].aspect + touch.swidth*2/SCR_H;
else
y2 = y1 + (( x2 - x1 ) / Touch_AspectRatio()) * g_DefaultButtons[i].aspect;
y2 = y1 + ( x2 - x1 ) * (SCR_W/SCR_H) * g_DefaultButtons[i].aspect;
}
IN_TouchCheckCoords( &x1, &y1, &x2, &y2 );
@@ -860,7 +818,6 @@ static void Touch_LoadDefaults_f( void )
button->flags |= g_DefaultButtons[i].flags;
button->aspect = g_DefaultButtons[i].aspect;
}
touch.configchanged = true;
}
// Add default button from client
@@ -953,7 +910,7 @@ static void Touch_AddButton_f( void )
if( aspect )
{
if( B( texturefile )[0] != '#' )
B( y2 ) = B( y1 ) + (( B( x2 ) - B( x1 )) / Touch_AspectRatio() ) * aspect;
B( y2 ) = B( y1 ) + ( B( x2 ) - B( x1 )) * ( SCR_W / SCR_H ) * aspect;
B( aspect ) = aspect;
}
}
@@ -961,39 +918,11 @@ static void Touch_AddButton_f( void )
static void Touch_EnableEdit_f( void )
{
touch_button_t *button;
float current_ratio = SCR_H/SCR_W;
if( touch.state == state_none )
touch.state = state_edit;
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
touch.move_button = NULL;
touch.configchanged = true;
/* try determine the best ratio
* User enters editor. Window now have correct size. Need to fix aspect ratio in some cases */
// Case A: no config was loaded, touch was generated with lower height, but window was resized higher, reset it to actual size
if( touch.actual_aspect_ratio > current_ratio )
touch.actual_aspect_ratio = current_ratio;
if( !touch.config_aspect_ratio )
touch.config_aspect_ratio = touch.actual_aspect_ratio;
// Case B: config was loaded, but window may be resized later, so keep y coordinate as is
touch.actual_aspect_ratio = current_ratio;
// convert coordinates to actual aspect ratio after it was updated
if( touch.config_aspect_ratio != touch.actual_aspect_ratio )
{
for( button = touch.list_user.first; button; button = button->next )
{
B(y1) /= touch.actual_aspect_ratio / touch.config_aspect_ratio;
B(y2) /= touch.actual_aspect_ratio / touch.config_aspect_ratio;
// clamp positions to make buttons visible by user
if( B(y2) > 1.0f )
{
B(y1) -= B(y2) - 1.0f;
B(y2) -= B(y2) - 1.0f;
}
}
touch.config_aspect_ratio = touch.actual_aspect_ratio;
}
}
static void Touch_DisableEdit_f( void )
@@ -1006,7 +935,7 @@ static void Touch_DisableEdit_f( void )
touch.edit = touch.selection = NULL;
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
if( touch_in_menu.value )
if( CVAR_TO_BOOL( touch_in_menu ))
{
Cvar_Set( "touch_in_menu", "0" );
}
@@ -1028,7 +957,7 @@ static void Touch_DeleteProfile_f( void )
static void Touch_InitEditor( void )
{
float x = 0.1f * (Touch_AspectRatio());
float x = 0.1f * (SCR_H/SCR_W);
float y = 0.05f;
touch_button_t *temp;
rgba_t color;
@@ -1064,7 +993,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;
@@ -1123,34 +1052,33 @@ void Touch_Init( void )
Cmd_AddRestrictedCommand( "touch_generate_code", Touch_GenerateCode_f, "create code sample for mobility API" );
Cmd_AddCommand( "touch_fade", Touch_Fade_f, "start fade animation for selected buttons" );
Cmd_AddRestrictedCommand( "touch_toggleselection", Touch_ToggleSelection_f, "toggle vidibility on selected button in editor" );
Cmd_AddRestrictedCommand( "touch_aspectratio", Touch_ConfigAspectRatio_f, "set current aspect ratio" );
// not saved, just runtime state for scripting
Cvar_RegisterVariable( &touch_in_menu );
touch_in_menu = Cvar_Get( "touch_in_menu", "0", FCVAR_FILTERABLE, "draw touch in menu (for internal use only)" );
// sensitivity configuration
Cvar_RegisterVariable( &touch_forwardzone );
Cvar_RegisterVariable( &touch_sidezone );
Cvar_RegisterVariable( &touch_pitch );
Cvar_RegisterVariable( &touch_yaw );
Cvar_RegisterVariable( &touch_nonlinear_look );
Cvar_RegisterVariable( &touch_pow_factor );
Cvar_RegisterVariable( &touch_pow_mult );
Cvar_RegisterVariable( &touch_exp_mult );
touch_forwardzone = Cvar_Get( "touch_forwardzone", "0.06", FCVAR_FILTERABLE, "forward touch zone" );
touch_sidezone = Cvar_Get( "touch_sidezone", "0.06", FCVAR_FILTERABLE, "side touch zone" );
touch_pitch = Cvar_Get( "touch_pitch", "90", FCVAR_FILTERABLE, "touch pitch sensitivity" );
touch_yaw = Cvar_Get( "touch_yaw", "120", FCVAR_FILTERABLE, "touch yaw sensitivity" );
touch_nonlinear_look = Cvar_Get( "touch_nonlinear_look", "0", FCVAR_FILTERABLE, "enable nonlinear touch look" );
touch_pow_factor = Cvar_Get( "touch_pow_factor", "1.3", FCVAR_FILTERABLE, "set > 1 to enable" );
touch_pow_mult = Cvar_Get( "touch_pow_mult", "400.0", FCVAR_FILTERABLE, "power multiplier, usually 200-1000" );
touch_exp_mult = Cvar_Get( "touch_exp_mult", "0", FCVAR_FILTERABLE, "exponent multiplier, usually 20-200, 0 to disable" );
// touch.cfg
Cvar_RegisterVariable( &touch_grid_count );
Cvar_RegisterVariable( &touch_grid_enable );
Cvar_RegisterVariable( &touch_config_file );
Cvar_RegisterVariable( &touch_precise_amount );
Cvar_RegisterVariable( &touch_highlight_r );
Cvar_RegisterVariable( &touch_highlight_g );
Cvar_RegisterVariable( &touch_highlight_b );
Cvar_RegisterVariable( &touch_highlight_a );
Cvar_RegisterVariable( &touch_dpad_radius );
Cvar_RegisterVariable( &touch_joy_radius );
Cvar_RegisterVariable( &touch_move_indicator );
Cvar_RegisterVariable( &touch_joy_texture );
touch_grid_count = Cvar_Get( "touch_grid_count", "50", FCVAR_FILTERABLE, "touch grid count" );
touch_grid_enable = Cvar_Get( "touch_grid_enable", "1", FCVAR_FILTERABLE, "enable touch grid" );
touch_config_file = Cvar_Get( "touch_config_file", "touch.cfg", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "current touch profile file" );
touch_precise_amount = Cvar_Get( "touch_precise_amount", "0.5", FCVAR_FILTERABLE, "sensitivity multiplier for precise-look" );
touch_highlight_r = Cvar_Get( "touch_highlight_r", "1.0", 0, "highlight r color" );
touch_highlight_g = Cvar_Get( "touch_highlight_g", "1.0", 0, "highlight g color" );
touch_highlight_b = Cvar_Get( "touch_highlight_b", "1.0", 0, "highlight b color" );
touch_highlight_a = Cvar_Get( "touch_highlight_a", "1.0", 0, "highlight alpha" );
touch_dpad_radius = Cvar_Get( "touch_dpad_radius", "1.0", FCVAR_FILTERABLE, "dpad radius multiplier" );
touch_joy_radius = Cvar_Get( "touch_joy_radius", "1.0", FCVAR_FILTERABLE, "joy radius multiplier" );
touch_move_indicator = Cvar_Get( "touch_move_indicator", "0.0", FCVAR_FILTERABLE, "indicate move events (0 to disable)" );
touch_joy_texture = Cvar_Get( "touch_joy_texture", "touch_default/joy", FCVAR_FILTERABLE, "texture for move indicator");
// input devices cvar
Cvar_RegisterVariable( &touch_enable );
@@ -1160,7 +1088,7 @@ void Touch_Init( void )
#if SDL_VERSION_ATLEAST( 2, 0, 10 )
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
#elif defined(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH)
#else
SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
#endif
@@ -1181,9 +1109,9 @@ static void Touch_InitConfig( void )
/// TODO: hud font
//pfnGetScreenInfo( NULL ); //HACK: update hud screen parameters like iHeight
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 );
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file->string );
Cbuf_Execute();
}
else
@@ -1192,7 +1120,7 @@ static void Touch_InitConfig( void )
}
Touch_InitEditor();
touch.joytexture = ref.dllFuncs.GL_LoadTexture( touch_joy_texture.string, NULL, 0, TF_NOMIPMAP );
touch.joytexture = ref.dllFuncs.GL_LoadTexture( touch_joy_texture->string, NULL, 0, TF_NOMIPMAP );
touch.whitetexture = R_GetBuiltinTexture( REF_WHITE_TEXTURE );
touch.configchanged = false;
touch.config_loaded = true;
@@ -1217,10 +1145,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;
@@ -1242,10 +1170,10 @@ static void Touch_DrawTexture ( float x1, float y1, float x2, float y2, int text
0, 0, 1, 1, texture );
}
#define GRID_COUNT_X ((int)touch_grid_count.value)
#define GRID_COUNT_Y (((int)touch_grid_count.value) * Touch_AspectRatio())
#define GRID_COUNT_X ((int)touch_grid_count->value)
#define GRID_COUNT_Y (((int)touch_grid_count->value) * SCR_H / SCR_W)
#define GRID_X (1.0f/GRID_COUNT_X)
#define GRID_Y (1.0f/Touch_AspectRatio()/GRID_COUNT_X)
#define GRID_Y (SCR_W/SCR_H/GRID_COUNT_X)
#define GRID_ROUND_X(x) ((float)round( x * GRID_COUNT_X ) / GRID_COUNT_X)
#define GRID_ROUND_Y(x) ((float)round( x * GRID_COUNT_Y ) / GRID_COUNT_Y)
@@ -1264,7 +1192,7 @@ static void IN_TouchCheckCoords( float *x1, float *y1, float *x2, float *y2 )
*y1 -= *y2 - 1, *y2 = 1;
if( *x2 > 1 )
*x1 -= *x2 - 1, *x2 = 1;
if( touch_grid_enable.value )
if( CVAR_TO_BOOL( touch_grid_enable ))
{
*x1 = GRID_ROUND_X( *x1 );
*x2 = GRID_ROUND_X( *x2 );
@@ -1323,7 +1251,7 @@ static float Touch_DrawText( float x1, float y1, float x2, float y2, const char
{
while( *s && ( *s != '\n' ) && ( *s != ';' ) && ( x1 < maxx ) )
x1 += Touch_DrawCharacter( x1, y1, *s++, size );
y1 += cls.creditsFont.charHeight / 1024.f * size / Touch_AspectRatio();
y1 += cls.creditsFont.charHeight / 1024.f * size / SCR_H * SCR_W;
if( y1 >= maxy )
break;
@@ -1360,10 +1288,10 @@ static void Touch_DrawButtons( touchbuttonlist_t *list )
if( ( B( finger ) != -1 ) && !FBitSet( B( flags ), TOUCH_FL_CLIENT ) )
{
color[0] = bound( 0,(float) color[0] * touch_highlight_r.value, 255 );
color[1] = bound( 0,(float) color[1] * touch_highlight_g.value, 255 );
color[2] = bound( 0,(float) color[2] * touch_highlight_b.value, 255 );
color[3] = bound( 0,(float) color[3] * touch_highlight_a.value, 255 );
color[0] = bound( 0,(float) color[0] * touch_highlight_r->value, 255 );
color[1] = bound( 0,(float) color[1] * touch_highlight_g->value, 255 );
color[2] = bound( 0,(float) color[2] * touch_highlight_b->value, 255 );
color[3] = bound( 0,(float) color[3] * touch_highlight_a->value, 255 );
}
color[3] *= B( fade );
@@ -1430,18 +1358,17 @@ void Touch_Draw( void )
if( !touch.initialized || ( !touch_enable.value && !touch.clientonly ))
return;
if( cls.key_dest != key_game && !touch_in_menu.value )
return;
Touch_InitConfig();
if( cls.key_dest != key_game && !CVAR_TO_BOOL(touch_in_menu) )
return;
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
if( touch.state >= state_edit && touch_grid_enable.value )
if( touch.state >= state_edit && CVAR_TO_BOOL(touch_grid_enable) )
{
float x;
if( touch_in_menu.value )
if( CVAR_TO_BOOL(touch_in_menu) )
Touch_DrawTexture( 0, 0, 1, 1, touch.whitetexture, 32, 32, 32, 255 );
else
Touch_DrawTexture( 0, 0, 1, 1, touch.whitetexture, 0, 0, 0, 112 );
@@ -1502,19 +1429,19 @@ void Touch_Draw( void )
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
if( ( touch.move_finger != -1 ) && touch.move_button && touch_move_indicator.value )
if( ( touch.move_finger != -1 ) && touch.move_button && touch_move_indicator->value )
{
float width;
float height;
if( FBitSet( touch_joy_texture.flags, FCVAR_CHANGED ) )
if( FBitSet( touch_joy_texture->flags, FCVAR_CHANGED ) )
{
ClearBits( touch_joy_texture.flags, FCVAR_CHANGED );
touch.joytexture = ref.dllFuncs.GL_LoadTexture( touch_joy_texture.string, NULL, 0, TF_NOMIPMAP );
ClearBits( touch_joy_texture->flags, FCVAR_CHANGED );
touch.joytexture = ref.dllFuncs.GL_LoadTexture( touch_joy_texture->string, NULL, 0, TF_NOMIPMAP );
}
if( touch.move_button->type == touch_move )
{
width = touch_sidezone.value;
height = touch_forwardzone.value;
width = touch_sidezone->value;
height = touch_forwardzone->value;
}
else
{
@@ -1522,13 +1449,13 @@ void Touch_Draw( void )
height = (touch.move_button->y2 - touch.move_button->y1)/2;
}
ref.dllFuncs.Color4ub( 255, 255, 255, 128 );
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x - GRID_X * touch_move_indicator.value ),
TO_SCRN_Y( touch.move_start_y - GRID_Y * touch_move_indicator.value ),
TO_SCRN_X( GRID_X * 2 * touch_move_indicator.value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator.value ), 0, 0, 1, 1, touch.joytexture );
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x - GRID_X * touch_move_indicator->value ),
TO_SCRN_Y( touch.move_start_y - GRID_Y * touch_move_indicator->value ),
TO_SCRN_X( GRID_X * 2 * touch_move_indicator->value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator->value ), 0, 0, 1, 1, touch.joytexture );
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x + touch.side * width - GRID_X * touch_move_indicator.value ),
TO_SCRN_Y( touch.move_start_y - touch.forward * height - GRID_Y * touch_move_indicator.value ),
TO_SCRN_X( GRID_X * 2 * touch_move_indicator.value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator.value ), 0, 0, 1, 1, touch.joytexture );
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x + touch.side * width - GRID_X * touch_move_indicator->value ),
TO_SCRN_Y( touch.move_start_y - touch.forward * height - GRID_Y * touch_move_indicator->value ),
TO_SCRN_X( GRID_X * 2 * touch_move_indicator->value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator->value ), 0, 0, 1, 1, touch.joytexture );
}
@@ -1637,28 +1564,28 @@ static void Touch_Motion( touchEventType type, int fingerID, float x, float y, f
if( fingerID == touch.move_finger )
{
// check bounds
if( touch_forwardzone.value <= 0 )
if( touch_forwardzone->value <= 0 )
Cvar_SetValue( "touch_forwardzone", 0.5 );
if( touch_sidezone.value <= 0 )
if( touch_sidezone->value <= 0 )
Cvar_SetValue( "touch_sidezone", 0.3 );
if( !touch.move_button || touch.move_button->type == touch_move )
{
// move relative to touch start
touch.forward = ( touch.move_start_y - y ) / touch_forwardzone.value;
touch.side = ( x - touch.move_start_x ) / touch_sidezone.value;
touch.forward = ( touch.move_start_y - y ) / touch_forwardzone->value;
touch.side = ( x - touch.move_start_x ) / touch_sidezone->value;
}
else if( touch.move_button->type == touch_joy )
{
// move relative to joy center
touch.forward = ( ( touch.move_button->y2 + touch.move_button->y1 ) - y * 2 ) / ( touch.move_button->y2 - touch.move_button->y1 ) * touch_joy_radius.value;
touch.side = ( x * 2 - ( touch.move_button->x2 + touch.move_button->x1 ) ) / ( touch.move_button->x2 - touch.move_button->x1 ) * touch_joy_radius.value;
touch.forward = ( ( touch.move_button->y2 + touch.move_button->y1 ) - y * 2 ) / ( touch.move_button->y2 - touch.move_button->y1 ) * touch_joy_radius->value;
touch.side = ( x * 2 - ( touch.move_button->x2 + touch.move_button->x1 ) ) / ( touch.move_button->x2 - touch.move_button->x1 ) * touch_joy_radius->value;
}
else if( touch.move_button->type == touch_dpad )
{
// like joy, but without acceleration. useful for bhop
touch.forward = round( ( (touch.move_button->y2 + touch.move_button->y1) - y * 2 ) / ( touch.move_button->y2 - touch.move_button->y1 ) * touch_dpad_radius.value );
touch.side = round( ( x * 2 - (touch.move_button->x2 + touch.move_button->x1) ) / ( touch.move_button->x2 - touch.move_button->x1 ) * touch_dpad_radius.value );
touch.forward = round( ( (touch.move_button->y2 + touch.move_button->y1) - y * 2 ) / ( touch.move_button->y2 - touch.move_button->y1 ) * touch_dpad_radius->value );
touch.side = round( ( x * 2 - (touch.move_button->x2 + touch.move_button->x1) ) / ( touch.move_button->x2 - touch.move_button->x1 ) * touch_dpad_radius->value );
}
touch.forward = bound( -1, touch.forward, 1 );
@@ -1669,9 +1596,9 @@ static void Touch_Motion( touchEventType type, int fingerID, float x, float y, f
if( fingerID == touch.look_finger )
{
if( touch.precision )
dx *= touch_precise_amount.value, dy *= touch_precise_amount.value;
dx *= touch_precise_amount->value, dy *= touch_precise_amount->value;
if( touch_nonlinear_look.value )
if( CVAR_TO_BOOL(touch_nonlinear_look) )
{
float dabs, dcos, dsin;
@@ -1684,11 +1611,11 @@ static void Touch_Motion( touchEventType type, int fingerID, float x, float y, f
dcos = dx / dabs;
dsin = dy / dabs;
if( touch_exp_mult.value > 1 )
dabs = ( exp( dabs * touch_exp_mult.value ) - 1 ) / touch_exp_mult.value;
if( touch_exp_mult->value > 1 )
dabs = ( exp( dabs * touch_exp_mult->value ) - 1 ) / touch_exp_mult->value;
if( touch_pow_mult.value > 1 && touch_pow_factor.value > 1 )
dabs = pow( dabs * touch_pow_mult.value, touch_pow_factor.value ) / touch_pow_mult.value;
if( touch_pow_mult->value > 1 && touch_pow_factor->value > 1 )
dabs = pow( dabs * touch_pow_mult->value, touch_pow_factor->value ) / touch_pow_mult->value;
dx = dabs * dcos;
dy = dabs * dsin;
@@ -1699,7 +1626,7 @@ static void Touch_Motion( touchEventType type, int fingerID, float x, float y, f
return;
// accumulate
touch.yaw -= dx * touch_yaw.value, touch.pitch += dy * touch_pitch.value;
touch.yaw -= dx * touch_yaw->value, touch.pitch += dy * touch_pitch->value;
}
}
@@ -2022,25 +1949,15 @@ static int Touch_ControlsEvent( touchEventType type, int fingerID, float x, floa
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy )
{
y *= SCR_H/SCR_W/Touch_AspectRatio();
// Con_Printf("%f %f\n", TO_SCRN_X(x), TO_SCRN_Y(y));
// simulate menu mouse click
if( cls.key_dest != key_game && !touch_in_menu.value )
if( cls.key_dest != key_game && !CVAR_TO_BOOL( touch_in_menu ))
{
touch.move_finger = touch.resize_finger = touch.look_finger = -1;
// Hack for keyboard, hope it help
// a1ba: this is absolutely horrible
if( cls.key_dest == key_console || cls.key_dest == key_message )
{
static float x1 = 0.0f;
x1 += dx;
if( type == event_up ) // don't show keyboard on every tap
{
if ( type == event_down ) // don't pop it again on event_up
Key_EnableTextInput( true, true );
x1 = 0.0f;
}
if( cls.key_dest == key_console )
{
static float y1 = 0;
@@ -2062,13 +1979,6 @@ int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx
// exit of console area
if( type == event_down && x < 0.1f && y > 0.9f )
Cbuf_AddText( "escape\n" );
// swipe from edge to exit console/chat
if(( x > 0.8f && x1 < -0.1f ) || ( x < 0.2f && x1 > 0.1f ))
{
Cbuf_AddText( "escape\n" );
x1 = 0.0f;
}
}
UI_MouseMove( TO_SCRN_X(x), TO_SCRN_Y(y) );
//MsgDev( D_NOTE, "touch %d %d\n", TO_SCRN_X(x), TO_SCRN_Y(y) );
@@ -2163,7 +2073,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 );

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>
@@ -37,15 +36,16 @@ static struct inputstate_s
float lastpitch, lastyaw;
} inputstate;
CVAR_DEFINE_AUTO( m_pitch, "0.022", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "mouse pitch value" );
CVAR_DEFINE_AUTO( m_yaw, "0.022", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "mouse yaw value" );
CVAR_DEFINE_AUTO( m_ignore, DEFAULT_M_IGNORE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "ignore mouse events" );
static CVAR_DEFINE_AUTO( look_filter, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "filter look events making it smoother" );
static CVAR_DEFINE_AUTO( m_rawinput, "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable mouse raw input" );
extern convar_t *vid_fullscreen;
convar_t *m_pitch;
convar_t *m_yaw;
static CVAR_DEFINE_AUTO( cl_forwardspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default forward move speed" );
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" );
convar_t *m_ignore;
convar_t *cl_forwardspeed;
convar_t *cl_sidespeed;
convar_t *cl_backspeed;
convar_t *look_filter;
convar_t *m_rawinput;
/*
================
@@ -58,7 +58,7 @@ uint IN_CollectInputDevices( void )
{
uint ret = 0;
if( !m_ignore.value ) // no way to check is mouse connected, so use cvar only
if( !m_ignore->value ) // no way to check is mouse connected, so use cvar only
ret |= INPUT_DEVICE_MOUSE;
if( touch_enable.value )
@@ -86,18 +86,18 @@ player is connected to the server
*/
void IN_LockInputDevices( qboolean lock )
{
extern convar_t joy_enable; // private to input system
extern convar_t *joy_enable; // private to input system
if( lock )
{
SetBits( m_ignore.flags, FCVAR_READ_ONLY );
SetBits( joy_enable.flags, FCVAR_READ_ONLY );
SetBits( m_ignore->flags, FCVAR_READ_ONLY );
SetBits( joy_enable->flags, FCVAR_READ_ONLY );
SetBits( touch_enable.flags, FCVAR_READ_ONLY );
}
else
{
ClearBits( m_ignore.flags, FCVAR_READ_ONLY );
ClearBits( joy_enable.flags, FCVAR_READ_ONLY );
ClearBits( m_ignore->flags, FCVAR_READ_ONLY );
ClearBits( joy_enable->flags, FCVAR_READ_ONLY );
ClearBits( touch_enable.flags, FCVAR_READ_ONLY );
}
}
@@ -108,14 +108,14 @@ void IN_LockInputDevices( qboolean lock )
IN_StartupMouse
===========
*/
static void IN_StartupMouse( void )
void IN_StartupMouse( void )
{
Cvar_RegisterVariable( &m_ignore );
m_ignore = Cvar_Get( "m_ignore", DEFAULT_M_IGNORE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "ignore mouse events" );
Cvar_RegisterVariable( &m_pitch );
Cvar_RegisterVariable( &m_yaw );
Cvar_RegisterVariable( &look_filter );
Cvar_RegisterVariable( &m_rawinput );
m_pitch = Cvar_Get( "m_pitch", "0.022", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "mouse pitch value" );
m_yaw = Cvar_Get( "m_yaw", "0.022", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "mouse yaw value" );
look_filter = Cvar_Get( "look_filter", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "filter look events making it smoother" );
m_rawinput = Cvar_Get( "m_rawinput", "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable mouse raw input" );
// You can use -nomouse argument to prevent using mouse from client
// -noenginemouse will disable all mouse input
@@ -124,6 +124,11 @@ static void IN_StartupMouse( void )
in_mouseinitialized = true;
}
void GAME_EXPORT IN_SetCursor( void *hCursor )
{
// stub
}
/*
===========
IN_MouseSavePos
@@ -175,6 +180,9 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
{
Platform_SetCursorType( dc_arrow );
#if XASH_ANDROID
Android_ShowMouse( true );
#endif
#if XASH_USE_EVDEV
Evdev_SetGrab( false );
#endif
@@ -183,15 +191,14 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
{
Platform_SetCursorType( dc_none );
#if XASH_ANDROID
Android_ShowMouse( false );
#endif
#if XASH_USE_EVDEV
Evdev_SetGrab( true );
#endif
}
// don't leave the user without cursor if they enabled m_ignore
if( m_ignore.value )
return;
if( oldstate == key_game )
{
IN_DeactivateMouse();
@@ -202,19 +209,16 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
}
}
static void IN_CheckMouseState( qboolean active )
void IN_CheckMouseState( qboolean active )
{
static qboolean s_bRawInput, s_bMouseGrab;
#if XASH_WIN32
qboolean useRawInput = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
qboolean useRawInput = ( CVAR_TO_BOOL( m_rawinput ) && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
#else
qboolean useRawInput = true; // always use SDL code
#endif
if( m_ignore.value )
return;
if( active && useRawInput && !host.mouse_visible && cls.state == ca_active )
{
if( !s_bRawInput )
@@ -309,7 +313,7 @@ void IN_DeactivateMouse( void )
IN_MouseMove
================
*/
static void IN_MouseMove( void )
void IN_MouseMove( void )
{
int x, y;
@@ -410,9 +414,9 @@ IN_Init
*/
void IN_Init( void )
{
Cvar_RegisterVariable( &cl_forwardspeed );
Cvar_RegisterVariable( &cl_backspeed );
Cvar_RegisterVariable( &cl_sidespeed );
cl_forwardspeed = Cvar_Get( "cl_forwardspeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default forward move speed" );
cl_backspeed = Cvar_Get( "cl_backspeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default back move speed" );
cl_sidespeed = Cvar_Get( "cl_sidespeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default side move speed" );
if( !Host_IsDedicated() )
{
@@ -449,8 +453,8 @@ static void IN_JoyAppendMove( usercmd_t *cmd, float forwardmove, float sidemove
{
static uint moveflags = T | S;
if( forwardmove ) cmd->forwardmove = forwardmove * cl_forwardspeed.value;
if( sidemove ) cmd->sidemove = sidemove * cl_sidespeed.value;
if( forwardmove ) cmd->forwardmove = forwardmove * cl_forwardspeed->value;
if( sidemove ) cmd->sidemove = sidemove * cl_sidespeed->value;
if( forwardmove )
{
@@ -525,8 +529,8 @@ static void IN_CollectInput( float *forward, float *side, float *pitch, float *y
{
float x, y;
Platform_MouseMove( &x, &y );
*pitch += y * m_pitch.value;
*yaw -= x * m_yaw.value;
*pitch += y * m_pitch->value;
*yaw -= x * m_yaw->value;
#if XASH_USE_EVDEV
IN_EvdevMove( yaw, pitch );
@@ -536,7 +540,7 @@ static void IN_CollectInput( float *forward, float *side, float *pitch, float *y
Joy_FinalizeMove( forward, side, yaw, pitch );
Touch_GetMove( forward, side, yaw, pitch );
if( look_filter.value )
if( look_filter->value )
{
*pitch = ( inputstate.lastpitch + *pitch ) / 2;
*yaw = ( inputstate.lastyaw + *yaw ) / 2;
@@ -584,7 +588,7 @@ void IN_EngineAppendMove( float frametime, void *cmd1, qboolean active )
}
}
static void IN_Commands( void )
void IN_Commands( void )
{
#if XASH_USE_EVDEV
IN_EvdevFrame();
@@ -594,7 +598,7 @@ static void IN_Commands( void )
{
float forward = 0, side = 0, pitch = 0, yaw = 0;
IN_CollectInput( &forward, &side, &pitch, &yaw, in_mouseinitialized && !m_ignore.value );
IN_CollectInput( &forward, &side, &pitch, &yaw, in_mouseinitialized && !CVAR_TO_BOOL( m_ignore ) );
if( cls.key_dest == key_game )
{

View File

@@ -40,13 +40,14 @@ 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, void *cmd, qboolean active );
extern convar_t m_yaw;
extern convar_t m_pitch;
extern convar_t *m_yaw;
extern convar_t *m_pitch;
//
// in_touch.c
//
@@ -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 );
void Touch_NotifyResize( void );
//
// in_joy.c

View File

@@ -144,8 +144,8 @@ keyname_t keynames[] =
static void OSK_EnableTextInput( qboolean enable, qboolean force );
static qboolean OSK_KeyEvent( int key, int down );
static CVAR_DEFINE_AUTO( osk_enable, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "enable built-in on-screen keyboard" );
static CVAR_DEFINE_AUTO( key_rotate, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "rotate arrow keys (0-3)" );
static convar_t *osk_enable;
static convar_t *key_rotate;
/*
===================
@@ -332,7 +332,7 @@ int Key_GetKey( const char *pBinding )
Key_Unbind_f
===================
*/
static void Key_Unbind_f( void )
void Key_Unbind_f( void )
{
int b;
@@ -358,7 +358,7 @@ static void Key_Unbind_f( void )
Key_Unbindall_f
===================
*/
static void Key_Unbindall_f( void )
void Key_Unbindall_f( void )
{
int i;
@@ -378,7 +378,7 @@ static void Key_Unbindall_f( void )
Key_Reset_f
===================
*/
static void Key_Reset_f( void )
void Key_Reset_f( void )
{
keyname_t *kn;
int i;
@@ -400,7 +400,7 @@ static void Key_Reset_f( void )
Key_Bind_f
===================
*/
static void Key_Bind_f( void )
void Key_Bind_f( void )
{
char cmd[1024];
int i, c, b;
@@ -473,7 +473,7 @@ Key_Bindlist_f
============
*/
static void Key_Bindlist_f( void )
void Key_Bindlist_f( void )
{
int i;
@@ -513,8 +513,8 @@ void Key_Init( void )
// setup default binding. "unbindall" from config.cfg will be reset it
for( kn = keynames; kn->name; kn++ ) Key_SetBinding( kn->keynum, kn->binding );
Cvar_RegisterVariable( &osk_enable );
Cvar_RegisterVariable( &key_rotate );
osk_enable = Cvar_Get( "osk_enable", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable built-in on-screen keyboard" );
key_rotate = Cvar_Get( "key_rotate", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "rotate arrow keys (0-3)" );
}
@@ -523,7 +523,7 @@ void Key_Init( void )
Key_AddKeyCommands
===================
*/
static void Key_AddKeyCommands( int key, const char *kb, qboolean down )
void Key_AddKeyCommands( int key, const char *kb, qboolean down )
{
char button[1024];
char *buttonPtr;
@@ -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++;
}
@@ -590,7 +590,7 @@ static qboolean Key_IsAllowedAutoRepeat( int key )
static int Key_Rotate( int key )
{
if( key_rotate.value == 1.0f ) // CW
if( key_rotate->value == 1.0f ) // CW
{
if( key == K_UPARROW )
key = K_LEFTARROW;
@@ -602,7 +602,7 @@ static int Key_Rotate( int key )
key = K_RIGHTARROW;
}
else if( key_rotate.value == 3.0f ) // CCW
else if( key_rotate->value == 3.0f ) // CCW
{
if( key == K_UPARROW )
key = K_RIGHTARROW;
@@ -614,7 +614,7 @@ static int Key_Rotate( int key )
key = K_LEFTARROW;
}
else if( key_rotate.value == 2.0f )
else if( key_rotate->value == 2.0f )
{
if( key == K_UPARROW )
key = K_DOWNARROW;
@@ -719,10 +719,10 @@ void GAME_EXPORT Key_Event( int key, int down )
switch( cls.key_dest )
{
case key_game:
if( r_showtextures.value )
if( CVAR_TO_BOOL( gl_showtextures ))
{
// close texture atlas
Cvar_DirectSet( &r_showtextures, "0" );
Cvar_SetValue( "r_showtextures", 0.0f );
return;
}
else if( host.mouse_visible && cls.state != ca_cinematic )
@@ -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 ) )
{
@@ -797,7 +797,7 @@ Key_EnableTextInput
*/
void Key_EnableTextInput( qboolean enable, qboolean force )
{
if( osk_enable.value )
if( CVAR_TO_BOOL( osk_enable ) )
{
OSK_EnableTextInput( enable, force );
return;
@@ -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;
}
}
@@ -995,7 +995,7 @@ struct osk_s
static qboolean OSK_KeyEvent( int key, int down )
{
if( !osk.enable || !osk_enable.value )
if( !osk.enable || !CVAR_TO_BOOL( osk_enable ) )
return false;
if( osk.sending )
@@ -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];
}
}
@@ -1187,7 +1190,7 @@ void OSK_Draw( void )
float x, y;
int i, j;
if( !osk.enable || !osk_enable.value || !osk.curbutton.val )
if( !osk.enable || !CVAR_TO_BOOL(osk_enable) || !osk.curbutton.val )
return;
// draw keyboard

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;
}
@@ -659,7 +659,7 @@ static void make_hull_windings( hull_t *hull, hull_model_t *model )
Con_Reportf( "%i hull polys\n", model->num_polys );
}
void Mod_InitDebugHulls( model_t *loadmodel )
void Mod_InitDebugHulls( void )
{
int i;
@@ -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,42 +8,14 @@
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, "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" );
CVAR_DEFINE_AUTO( gl_msaa_samples, "0", FCVAR_GLCONFIG, "samples number for multisample anti-aliasing" );
CVAR_DEFINE_AUTO( gl_clear, "0", FCVAR_ARCHIVE, "clearing screen after each frame" );
CVAR_DEFINE_AUTO( r_showtree, "0", FCVAR_ARCHIVE, "build the graph of visible BSP tree" );
static CVAR_DEFINE_AUTO( r_refdll, "", FCVAR_RENDERINFO, "choose renderer implementation, if supported" );
static CVAR_DEFINE_AUTO( r_refdll_loaded, "", FCVAR_READ_ONLY, "currently loaded renderer" );
// there is no need to expose whole host and cl structs into the renderer
// but we still need to update timings accurately as possible
// this looks horrible but the only other option would be passing four
// time pointers and then it's looks even worse with dereferences everywhere
#define STATIC_OFFSET_CHECK( s1, s2, field, base, msg ) \
STATIC_ASSERT( offsetof( s1, field ) == offsetof( s2, field ) - offsetof( s2, base ), msg )
#define REF_CLIENT_CHECK( field ) \
STATIC_OFFSET_CHECK( ref_client_t, client_t, field, time, "broken ref_client_t offset" ); \
STATIC_ASSERT_( szchk_##__LINE__, sizeof(((ref_client_t *)0)->field ) == sizeof( cl.field ), "broken ref_client_t size" )
#define REF_HOST_CHECK( field ) \
STATIC_OFFSET_CHECK( ref_host_t, host_parm_t, field, realtime, "broken ref_client_t offset" ); \
STATIC_ASSERT_( szchk_##__LINE__, sizeof(((ref_host_t *)0)->field ) == sizeof( host.field ), "broken ref_client_t size" )
REF_CLIENT_CHECK( time );
REF_CLIENT_CHECK( oldtime );
REF_CLIENT_CHECK( viewentity );
REF_CLIENT_CHECK( playernum );
REF_CLIENT_CHECK( maxclients );
REF_CLIENT_CHECK( models );
REF_CLIENT_CHECK( paused );
REF_CLIENT_CHECK( simorg );
REF_HOST_CHECK( realtime );
REF_HOST_CHECK( frametime );
REF_HOST_CHECK( features );
convar_t *gl_vsync;
convar_t *gl_showtextures;
convar_t *r_decals;
convar_t *r_adjust_fov;
convar_t *r_showtree;
convar_t *gl_msaa_samples;
convar_t *gl_clear;
convar_t *r_refdll;
void R_GetTextureParms( int *w, int *h, int texnum )
{
@@ -51,102 +23,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;
@@ -158,8 +41,18 @@ void GAME_EXPORT GL_FreeImage( const char *name )
ref.dllFuncs.GL_FreeTexture( texnum );
}
void R_UpdateRefState( void )
{
refState.time = cl.time;
refState.oldtime = cl.oldtime;
refState.realtime = host.realtime;
refState.frametime = host.frametime;
}
void GL_RenderFrame( const ref_viewpass_t *rvp )
{
R_UpdateRefState();
VectorCopy( rvp->vieworigin, refState.vieworg );
VectorCopy( rvp->viewangles, refState.viewangles );
@@ -171,6 +64,11 @@ static intptr_t pfnEngineGetParm( int parm, int arg )
return CL_RenderGetParm( parm, arg, false ); // prevent recursion
}
static world_static_t *pfnGetWorld( void )
{
return &world;
}
static void pfnStudioEvent( const mstudioevent_t *event, const cl_entity_t *e )
{
clgame.dllFuncs.pfnStudioEvent( event, e );
@@ -182,7 +80,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;
}
@@ -195,15 +93,29 @@ 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;
}
static void CL_ExtraUpdate( void )
static model_t *pfnMod_GetCurrentLoadingModel( void )
{
clgame.dllFuncs.IN_Accumulate();
S_ExtraUpdate();
return loadmodel;
}
static void pfnMod_SetCurrentLoadingModel( model_t *m )
{
loadmodel = m;
}
static void pfnGetPredictedOrigin( vec3_t v )
{
VectorCopy( cl.simorg, v );
}
static color24 *pfnCL_GetPaletteColor( int color ) // clgame.palette[color]
{
return &clgame.palette[color];
}
static void pfnCL_GetScreenInfo( int *width, int *height ) // clgame.scrInfo, ptrs may be NULL
@@ -255,6 +167,11 @@ static int pfnGetStudioModelInterface( int version, struct r_studio_interface_s
0;
}
static poolhandle_t pfnImage_GetPool( void )
{
return host.imagepool;
}
static const bpc_desc_t *pfnImage_GetPFDesc( int idx )
{
return &PFDesc[idx];
@@ -275,6 +192,25 @@ static screenfade_t *pfnRefGetScreenFade( void )
return &clgame.fade;
}
/*
===============
R_DoResetGamma
gamma will be reset for
some type of screenshots
===============
*/
static qboolean R_DoResetGamma( void )
{
switch( cls.scrshot_action )
{
case scrshot_envshot:
case scrshot_skyshot:
return true;
default:
return false;
}
}
static qboolean R_Init_Video_( const int type )
{
host.apply_opengl_config = true;
@@ -295,7 +231,7 @@ static ref_api_t gEngfuncs =
Cvar_VariableString,
Cvar_SetValue,
Cvar_Set,
Cvar_RegisterVariable,
(void*)Cvar_RegisterVariable,
Cvar_FullSet,
Cmd_AddRefCommand,
@@ -319,12 +255,16 @@ static ref_api_t gEngfuncs =
Con_DrawString,
CL_DrawCenterPrint,
CL_GetLocalPlayer,
CL_GetViewModel,
CL_GetEntityByIndex,
R_BeamGetEntity,
CL_GetWaterEntity,
CL_AddVisibleEntity,
Mod_SampleSizeForFace,
Mod_BoxVisible,
pfnGetWorld,
Mod_PointInLeaf,
Mod_CreatePolygonsForHull,
@@ -341,9 +281,14 @@ static ref_api_t gEngfuncs =
Mod_ForName,
pfnMod_Extradata,
CL_ModelHandle,
pfnMod_GetCurrentLoadingModel,
pfnMod_SetCurrentLoadingModel,
CL_EntitySetRemapColors,
CL_GetRemapInfoForEntity,
CL_AllocRemapInfo,
CL_FreeRemapInfo,
CL_UpdateRemapInfo,
CL_ExtraUpdate,
Host_Error,
@@ -351,6 +296,9 @@ static ref_api_t gEngfuncs =
COM_RandomFloat,
COM_RandomLong,
pfnRefGetScreenFade,
CL_TextMessageGet,
pfnGetPredictedOrigin,
pfnCL_GetPaletteColor,
pfnCL_GetScreenInfo,
pfnSetLocalLightLevel,
Sys_CheckParm,
@@ -384,11 +332,9 @@ static ref_api_t gEngfuncs =
SW_LockBuffer,
SW_UnlockBuffer,
BuildGammaTable,
LightToTexGamma,
LightToTexGammaEx,
TextureToGamma,
ScreenGammaTable,
LinearGammaTable,
R_DoResetGamma,
CL_GetLightStyle,
CL_GetDynamicLight,
@@ -402,6 +348,7 @@ static ref_api_t gEngfuncs =
PM_CL_TraceLine,
CL_VisTraceLine,
CL_TraceLine,
pfnGetMoveVars,
Image_AddCmdFlags,
Image_SetForceFlags,
@@ -413,6 +360,7 @@ static ref_api_t gEngfuncs =
FS_CopyImage,
FS_FreeImage,
Image_SetMDLPointer,
pfnImage_GetPool,
pfnImage_GetPFDesc,
pfnDrawNormalTriangles,
@@ -431,14 +379,14 @@ static void R_UnloadProgs( void )
Cvar_FullSet( "host_refloaded", "0", FCVAR_READ_ONLY );
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG );
Cmd_Unlink( CMD_REFDLL );
COM_FreeLibrary( ref.hInstance );
ref.hInstance = NULL;
memset( &refState, 0, sizeof( refState ));
memset( &ref.dllFuncs, 0, sizeof( ref.dllFuncs ));
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG );
Cmd_Unlink( CMD_REFDLL );
}
static void CL_FillTriAPIFromRef( triangleapi_t *dst, const ref_interface_t *src )
@@ -467,6 +415,7 @@ 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
@@ -476,7 +425,7 @@ static qboolean R_LoadProgs( const char *name )
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;
}
@@ -485,7 +434,7 @@ static qboolean R_LoadProgs( const char *name )
if( !( GetRefAPI = (REFAPI)COM_GetProcAddress( ref.hInstance, GET_REF_API )) )
{
COM_FreeLibrary( ref.hInstance );
Con_Reportf( "%s: can't find GetRefAPI entry point in %s\n", __func__, name );
Con_Reportf( "R_LoadProgs: can't find GetRefAPI entry point in %s\n", name );
ref.hInstance = NULL;
return false;
}
@@ -493,10 +442,10 @@ static qboolean R_LoadProgs( const char *name )
// make local copy of engfuncs to prevent overwrite it with user dll
memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs ));
if( GetRefAPI( REF_API_VERSION, &ref.dllFuncs, &gpEngfuncs, &refState ) != REF_API_VERSION )
if( !GetRefAPI( REF_API_VERSION, &ref.dllFuncs, &gpEngfuncs, &refState ))
{
COM_FreeLibrary( ref.hInstance );
Con_Reportf( "%s: can't init renderer API: wrong version\n", __func__ );
Con_Reportf( "R_LoadProgs: can't init renderer API: wrong version\n" );
ref.hInstance = NULL;
return false;
}
@@ -506,7 +455,7 @@ static qboolean R_LoadProgs( const char *name )
if( !ref.dllFuncs.R_Init( ) )
{
COM_FreeLibrary( ref.hInstance );
Con_Reportf( "%s: can't init renderer!\n", __func__ ); //, ref.dllFuncs.R_GetInitError() );
Con_Reportf( "R_LoadProgs: can't init renderer!\n" ); //, ref.dllFuncs.R_GetInitError() );
ref.hInstance = NULL;
return false;
}
@@ -582,7 +531,6 @@ static qboolean R_LoadRenderer( const char *refopt )
return false;
}
Cvar_FullSet( "r_refdll_loaded", refopt, FCVAR_READ_ONLY );
Con_Reportf( "Renderer %s initialized\n", refdll );
return true;
@@ -601,17 +549,21 @@ static void SetWidthAndHeightFromCommandLine( void )
return;
}
R_SaveVideoMode( width, height, width, height, false );
R_SaveVideoMode( width, height, width, height );
}
static void SetFullscreenModeFromCommandLine( void )
{
if( Sys_CheckParm( "-borderless" ))
Cvar_DirectSet( &vid_fullscreen, "2" );
else if( Sys_CheckParm( "-fullscreen" ))
Cvar_DirectSet( &vid_fullscreen, "1" );
#if !XASH_MOBILE_PLATFORM
if( Sys_CheckParm( "-fullscreen" ))
{
Cvar_Set( "fullscreen", "1" );
}
else if( Sys_CheckParm( "-windowed" ))
Cvar_DirectSet( &vid_fullscreen, "0" );
{
Cvar_Set( "fullscreen", "0" );
}
#endif
}
static void R_CollectRendererNames( void )
@@ -631,9 +583,6 @@ static void R_CollectRendererNames( void )
#if XASH_REF_GL4ES_ENABLED
"gl4es",
#endif
#if XASH_REF_GLES3COMPAT_ENABLED
"gles3compat",
#endif
#if XASH_REF_SOFT_ENABLED
"soft",
#endif
@@ -654,9 +603,6 @@ static void R_CollectRendererNames( void )
#if XASH_REF_GL4ES_ENABLED
"GL4ES",
#endif
#if XASH_REF_GLES3COMPAT_ENABLED
"GLES3 (gl2_shim)",
#endif
#if XASH_REF_SOFT_ENABLED
"Software",
#endif
@@ -672,15 +618,14 @@ qboolean R_Init( void )
qboolean success = false;
string requested;
Cvar_RegisterVariable( &gl_vsync );
Cvar_RegisterVariable( &r_showtextures );
Cvar_RegisterVariable( &r_adjust_fov );
Cvar_RegisterVariable( &r_decals );
Cvar_RegisterVariable( &gl_msaa_samples );
Cvar_RegisterVariable( &gl_clear );
Cvar_RegisterVariable( &r_showtree );
Cvar_RegisterVariable( &r_refdll );
Cvar_RegisterVariable( &r_refdll_loaded );
gl_vsync = Cvar_Get( "gl_vsync", "0", FCVAR_ARCHIVE, "enable vertical syncronization" );
gl_showtextures = Cvar_Get( "r_showtextures", "0", FCVAR_CHEAT, "show all uploaded textures" );
r_adjust_fov = Cvar_Get( "r_adjust_fov", "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" );
r_decals = Cvar_Get( "r_decals", "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
gl_msaa_samples = Cvar_Get( "gl_msaa_samples", "0", FCVAR_GLCONFIG, "samples number for multisample anti-aliasing" );
gl_clear = Cvar_Get( "gl_clear", "0", FCVAR_ARCHIVE, "clearing screen after each frame" );
r_showtree = Cvar_Get( "r_showtree", "0", FCVAR_ARCHIVE, "build the graph of visible BSP tree" );
r_refdll = Cvar_Get( "r_refdll", "", FCVAR_RENDERINFO, "choose renderer implementation, if supported" );
// cvars that are expected to exist
Cvar_Get( "r_speeds", "0", FCVAR_ARCHIVE, "shows renderer speeds" );
@@ -701,7 +646,6 @@ qboolean R_Init( void )
// cvars that are expected to exist by client.dll
// refdll should just get pointer to them
Cvar_Get( "r_lighting_modulate", "0.6", FCVAR_ARCHIVE, "compatibility cvar, does nothing" );
Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" );
Cvar_Get( "cl_himodels", "1", FCVAR_ARCHIVE, "draw high-resolution player models in multiplayer" );
@@ -725,9 +669,9 @@ qboolean R_Init( void )
if( !success && Sys_GetParmFromCmdLine( "-ref", requested ))
success = R_LoadRenderer( requested );
if( !success && COM_CheckString( r_refdll.string ))
if( !success && COM_CheckString( r_refdll->string ))
{
Q_strncpy( requested, r_refdll.string, sizeof( requested ));
Q_strncpy( requested, r_refdll->string, sizeof( requested ));
success = R_LoadRenderer( requested );
}
@@ -747,7 +691,7 @@ qboolean R_Init( void )
if( !success )
{
Host_Error( "Can't initialize any renderer. Check your video drivers!\n" );
Host_Error( "Can't initialize any renderer. Check your video drivers!" );
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,15 @@ 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 gl_clear;
extern convar_t *r_decals;
extern convar_t *r_adjust_fov;
extern convar_t *gl_clear;
qboolean R_Init( void );
void R_Shutdown( void );
void R_UpdateRefState( void );
extern triangleapi_t gTriApi;
#endif // REF_COMMON_H

View File

@@ -1,7 +1,6 @@
/*
s_dsp.c - digital signal processing algorithms for audio FX
Copyright (C) 2009 Uncle Mike
Copyright (C) 2016-2024 Alibek Omarov
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
@@ -79,7 +78,7 @@ typedef struct dly_s
int *lpdelayline;
} dly_t;
static const sx_preset_t rgsxpre[] =
const sx_preset_t rgsxpre[] =
{
// -------reverb-------- -------delay--------
// lp mod size refl rvblp delay feedback dlylp left
@@ -116,7 +115,7 @@ static const sx_preset_t rgsxpre[] =
// 0x0045dca8 enginegl.exe
// SHA256: 42383d32cd712e59ee2c1bd78b7ba48814e680e7026c4223e730111f34a60d66
static const sx_preset_t rgsxpre_hlalpha052[] =
const sx_preset_t rgsxpre_hlalpha052[] =
{
// -------reverb-------- -------delay--------
// lp mod size refl rvblp delay feedback dlylp left
@@ -151,51 +150,51 @@ static const sx_preset_t rgsxpre_hlalpha052[] =
{ 0.0, 0.0, 0.001, 0.999, 0.0, 0.2, 0.8, 2.0, 0.05 }, // 28
};
static const sx_preset_t *ptable = rgsxpre;
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_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" );
static CVAR_DEFINE( roomwater_type, "waterroom_type", "14", 0, "water room type" );
static CVAR_DEFINE( hisound, "room_hires", "2", FCVAR_ARCHIVE, "dsp quality. 1 for 22k, 2 for 44k(recommended) and 3 for 96k" );
convar_t *dsp_off; // disable dsp
convar_t *roomwater_type; // water room_type
convar_t *room_type; // current room type
convar_t *hisound; // DSP quality
// underwater/special fx modulations
static CVAR_DEFINE( sxmod_mod, "room_mod", "0", 0, "stereo amptitude modulation for room" );
static CVAR_DEFINE( sxmod_lowpass, "room_lp", "0", 0, "for water fx, lowpass for entire room" );
convar_t *sxmod_mod;
convar_t *sxmod_lowpass;
// stereo delay(no feedback)
static CVAR_DEFINE( sxste_delay, "room_left", "0", 0, "left channel delay time" );
convar_t *sxste_delay; // straight left delay
// mono reverb
static CVAR_DEFINE( sxrvb_lp, "room_rvblp", "1", 0, "reverb: low pass filtering level" );
static CVAR_DEFINE( sxrvb_feedback, "room_refl", "0", 0, "reverb: decay time" );
static CVAR_DEFINE( sxrvb_size, "room_size", "0", 0, "reverb: initial reflection size" );
convar_t *sxrvb_lp; // lowpass
convar_t *sxrvb_feedback; // reverb decay. Higher -- longer
convar_t *sxrvb_size; // room size. Higher -- larger
// mono delay
static CVAR_DEFINE( sxdly_lp, "room_dlylp", "1", 0, "mono delay: low pass filtering level" );
static CVAR_DEFINE( sxdly_feedback, "room_feedback", "0.2", 0, "mono delay: decay time" );
static CVAR_DEFINE( sxdly_delay, "room_delay", "0.8", 0, "mono delay: delay time" );
convar_t *sxdly_lp; // lowpass
convar_t *sxdly_feedback; // cycles
convar_t *sxdly_delay; // current delay in seconds
static int idsp_dma_speed;
convar_t *dsp_room; // for compability
convar_t *dsp_coeff_table; // use release or 0.52 style
int idsp_dma_speed;
int idsp_room;
static int room_typeprev;
int room_typeprev;
// routines
static int sxamodl, sxamodr; // amplitude modulation values
static int sxamodlt, sxamodrt; // modulation targets
static int sxmod1cur, sxmod2cur;
static int sxmod1, sxmod2;
static int sxhires;
int sxamodl, sxamodr; // amplitude modulation values
int sxamodlt, sxamodrt; // modulation targets
int sxmod1cur, sxmod2cur;
int sxmod1, sxmod2;
int sxhires;
static portable_samplepair_t *paintto = NULL;
portable_samplepair_t *paintto = NULL;
static dly_t rgsxdly[MAXDLY]; // stereo is last
static int rgsxlp[MAXLP];
dly_t rgsxdly[MAXDLY]; // stereo is last
int rgsxlp[MAXLP];
static void SX_Profiling_f( void );
void SX_Profiling_f( void );
/*
============
@@ -203,12 +202,14 @@ SX_ReloadRoomFX
============
*/
static void SX_ReloadRoomFX( void )
void SX_ReloadRoomFX( void )
{
SetBits( sxste_delay.flags, FCVAR_CHANGED );
SetBits( sxrvb_feedback.flags, FCVAR_CHANGED );
SetBits( sxdly_delay.flags, FCVAR_CHANGED );
SetBits( room_type.flags, FCVAR_CHANGED );
if( !dsp_room ) return; // not initialized
SetBits( sxste_delay->flags, FCVAR_CHANGED );
SetBits( sxrvb_feedback->flags, FCVAR_CHANGED );
SetBits( sxdly_delay->flags, FCVAR_CHANGED );
SetBits( room_type->flags, FCVAR_CHANGED );
}
/*
@@ -226,34 +227,36 @@ void SX_Init( void )
sxamodr = sxamodl = sxamodrt = sxamodlt = 255;
idsp_dma_speed = SOUND_11k;
Cvar_RegisterVariable( &hisound );
hisound = Cvar_Get( "room_hires", "2", FCVAR_ARCHIVE, "dsp quality. 1 for 22k, 2 for 44k(recommended) and 3 for 96k" );
sxhires = 2;
sxmod1cur = sxmod1 = 350 * ( idsp_dma_speed / SOUND_11k );
sxmod2cur = sxmod2 = 450 * ( idsp_dma_speed / SOUND_11k );
Cvar_RegisterVariable( &dsp_off );
Cvar_RegisterVariable( &room_off );
Cvar_RegisterVariable( &dsp_coeff_table );
dsp_off = Cvar_Get( "dsp_off", "0", FCVAR_ARCHIVE, "disable DSP processing" );
dsp_coeff_table = Cvar_Get( "dsp_coeff_table", "0", FCVAR_ARCHIVE, "select DSP coefficient table: 0 for release or 1 for alpha 0.52" );
Cvar_RegisterVariable( &roomwater_type );
Cvar_RegisterVariable( &room_type );
roomwater_type = Cvar_Get( "waterroom_type", "14", 0, "water room type" );
room_type = Cvar_Get( "room_type", "0", 0, "current room type preset" );
Cvar_RegisterVariable( &sxmod_lowpass );
Cvar_RegisterVariable( &sxmod_mod );
sxmod_lowpass = Cvar_Get( "room_lp", "0", 0, "for water fx, lowpass for entire room" );
sxmod_mod = Cvar_Get( "room_mod", "0", 0, "stereo amptitude modulation for room" );
Cvar_RegisterVariable( &sxrvb_size );
Cvar_RegisterVariable( &sxrvb_feedback );
Cvar_RegisterVariable( &sxrvb_lp );
sxrvb_size = Cvar_Get( "room_size", "0", 0, "reverb: initial reflection size" );
sxrvb_feedback = Cvar_Get( "room_refl", "0", 0, "reverb: decay time" );
sxrvb_lp = Cvar_Get( "room_rvblp", "1", 0, "reverb: low pass filtering level" );
Cvar_RegisterVariable( &sxdly_delay );
Cvar_RegisterVariable( &sxdly_feedback );
Cvar_RegisterVariable( &sxdly_lp );
sxdly_delay = Cvar_Get( "room_delay", "0.8", 0, "mono delay: delay time" );
sxdly_feedback = Cvar_Get( "room_feedback", "0.2", 0, "mono delay: decay time" );
sxdly_lp = Cvar_Get( "room_dlylp", "1", 0, "mono delay: low pass filtering level" );
Cvar_RegisterVariable( &sxste_delay );
sxste_delay = Cvar_Get( "room_left", "0", 0, "left channel delay time" );
Cmd_AddCommand( "dsp_profile", SX_Profiling_f, "dsp stress-test, first argument is room_type" );
// for compability
dsp_room = room_type;
SX_ReloadRoomFX();
}
@@ -264,7 +267,7 @@ DLY_Free
Free memory allocated for DSP
===========
*/
static void DLY_Free( int idelay )
void DLY_Free( int idelay )
{
Assert( idelay >= 0 && idelay < MAXDLY );
@@ -300,7 +303,7 @@ DLY_Init
Initialize dly
===========
*/
static int DLY_Init( int idelay, float delay )
int DLY_Init( int idelay, float delay )
{
dly_t *cur;
@@ -336,7 +339,7 @@ DLY_MovePointer
Checks overflow and moves pointer
============
*/
static void DLY_MovePointer( dly_t *dly )
_inline void DLY_MovePointer( dly_t *dly )
{
if( ++dly->idelayinput >= dly->cdelaysamplesmax )
dly->idelayinput = 0;
@@ -352,12 +355,12 @@ DLY_CheckNewStereoDelayVal
Update stereo processor settings if we are in new room
=============
*/
static void DLY_CheckNewStereoDelayVal( void )
void DLY_CheckNewStereoDelayVal( void )
{
dly_t *const dly = &rgsxdly[STEREODLY];
float delay = sxste_delay.value;
float delay = sxste_delay->value;
if( !FBitSet( sxste_delay.flags, FCVAR_CHANGED ))
if( !FBitSet( sxste_delay->flags, FCVAR_CHANGED ))
return;
if( delay == 0 )
@@ -400,7 +403,7 @@ DLY_DoStereoDelay
Do stereo processing
=============
*/
static void DLY_DoStereoDelay( int count )
void DLY_DoStereoDelay( int count )
{
int delay, samplexf;
dly_t *const dly = &rgsxdly[STEREODLY];
@@ -465,12 +468,12 @@ DLY_CheckNewDelayVal
Update delay processor settings if we are in new room
=============
*/
static void DLY_CheckNewDelayVal( void )
void DLY_CheckNewDelayVal( void )
{
float delay = sxdly_delay.value;
float delay = sxdly_delay->value;
dly_t *const dly = &rgsxdly[MONODLY];
if( FBitSet( sxdly_delay.flags, FCVAR_CHANGED ))
if( FBitSet( sxdly_delay->flags, FCVAR_CHANGED ))
{
if( delay == 0 )
{
@@ -500,8 +503,8 @@ static void DLY_CheckNewDelayVal( void )
}
}
dly->lp = sxdly_lp.value;
dly->delayfeedback = 255 * sxdly_feedback.value;
dly->lp = sxdly_lp->value;
dly->delayfeedback = 255 * sxdly_feedback->value;
}
/*
@@ -511,7 +514,7 @@ DLY_DoDelay
Do delay processing
=============
*/
static void DLY_DoDelay( int count )
void DLY_DoDelay( int count )
{
dly_t *const dly = &rgsxdly[MONODLY];
portable_samplepair_t *paint = paintto;
@@ -562,7 +565,7 @@ RVB_SetUpDly
Set up dly for reverb
===========
*/
static void RVB_SetUpDly( int pos, float delay, int kmod )
void RVB_SetUpDly( int pos, float delay, int kmod )
{
int samples;
@@ -598,13 +601,13 @@ RVB_CheckNewReverbVal
Update reverb settings if we are in new room
===========
*/
static void RVB_CheckNewReverbVal( void )
void RVB_CheckNewReverbVal( void )
{
dly_t *const dly1 = &rgsxdly[REVERBPOS];
dly_t *const dly2 = &rgsxdly[REVERBPOS + 1];
float delay = sxrvb_size.value;
float delay = sxrvb_size->value;
if( FBitSet( sxrvb_size.flags, FCVAR_CHANGED ))
if( FBitSet( sxrvb_size->flags, FCVAR_CHANGED ))
{
if( delay == 0.0f )
{
@@ -613,13 +616,13 @@ static void RVB_CheckNewReverbVal( void )
}
else
{
RVB_SetUpDly( REVERBPOS, sxrvb_size.value, 500 );
RVB_SetUpDly( REVERBPOS+1, sxrvb_size.value * 0.71f, 700 );
RVB_SetUpDly( REVERBPOS, sxrvb_size->value, 500 );
RVB_SetUpDly( REVERBPOS+1, sxrvb_size->value * 0.71f, 700 );
}
}
dly1->lp = dly2->lp = sxrvb_lp.value;
dly1->delayfeedback = dly2->delayfeedback = (int)(255 * sxrvb_feedback.value);
dly1->lp = dly2->lp = sxrvb_lp->value;
dly1->delayfeedback = dly2->delayfeedback = (int)(255 * sxrvb_feedback->value);
}
/*
@@ -629,7 +632,7 @@ RVB_DoReverbForOneDly
Do reverberation for one dly
===========
*/
static int RVB_DoReverbForOneDly( dly_t *dly, const int vlr, const portable_samplepair_t *samplepair )
int RVB_DoReverbForOneDly( dly_t *dly, const int vlr, const portable_samplepair_t *samplepair )
{
int delay;
int samplexf;
@@ -703,7 +706,7 @@ RVB_DoReverb
Do reverberation processing
===========
*/
static void RVB_DoReverb( int count )
void RVB_DoReverb( int count )
{
dly_t *const dly1 = &rgsxdly[REVERBPOS];
dly_t *const dly2 = &rgsxdly[REVERBPOS+1];
@@ -720,7 +723,7 @@ static void RVB_DoReverb( int count )
voutm = RVB_DoReverbForOneDly( dly1, vlr, paint );
voutm += RVB_DoReverbForOneDly( dly2, vlr, paint );
if( dsp_coeff_table.value == 1.0f )
if( dsp_coeff_table->value == 1.0f )
voutm /= 6; // alpha
else voutm = (11 * voutm) >> 6;
@@ -736,18 +739,18 @@ RVB_DoAMod
Do amplification modulation processing
===========
*/
static void RVB_DoAMod( int count )
void RVB_DoAMod( int count )
{
portable_samplepair_t *paint = paintto;
if( !sxmod_lowpass.value && !sxmod_mod.value )
if( !sxmod_lowpass->value && !sxmod_mod->value )
return;
for( ; count; count--, paint++ )
{
portable_samplepair_t res = *paint;
if( sxmod_lowpass.value )
if( sxmod_lowpass->value )
{
res.left = rgsxlp[0] + rgsxlp[1] + rgsxlp[2] + rgsxlp[3] + rgsxlp[4] + res.left;
res.right = rgsxlp[5] + rgsxlp[6] + rgsxlp[7] + rgsxlp[8] + rgsxlp[9] + res.right;
@@ -769,7 +772,7 @@ static void RVB_DoAMod( int count )
rgsxlp[8] = rgsxlp[9];
}
if( sxmod_mod.value )
if( sxmod_mod->value )
{
if( --sxmod1cur < 0 )
sxmod1cur = sxmod1;
@@ -809,9 +812,13 @@ DSP_Process
(xash dsp interface)
===========
*/
void DSP_Process( portable_samplepair_t *pbfront, int sampleCount )
void DSP_Process( int idsp, portable_samplepair_t *pbfront, int sampleCount )
{
if( dsp_off.value || room_off.value || !sampleCount )
if( dsp_off->value )
return;
// don't process DSP while in menu
if( cls.key_dest == key_menu || !sampleCount )
return;
// preset is already installed by CheckNewDspPresets
@@ -832,7 +839,7 @@ DSP_ClearState
*/
void DSP_ClearState( void )
{
Cvar_DirectSet( &room_type, "0" );
Cvar_SetValue( "room_type", 0.0f );
SX_ReloadRoomFX();
}
@@ -845,12 +852,12 @@ 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 ))
if( FBitSet( dsp_coeff_table->flags, FCVAR_CHANGED ))
{
switch( (int)dsp_coeff_table.value )
switch( (int)dsp_coeff_table->value )
{
case 0: // release
ptable = rgsxpre;
@@ -866,20 +873,20 @@ void CheckNewDspPresets( void )
SX_ReloadRoomFX();
room_typeprev = -1;
ClearBits( dsp_coeff_table.flags, FCVAR_CHANGED );
ClearBits( dsp_coeff_table->flags, FCVAR_CHANGED );
}
if( s_listener.waterlevel > 2 )
idsp_room = roomwater_type.value;
else idsp_room = room_type.value;
idsp_room = roomwater_type->value;
else idsp_room = room_type->value;
// don't pass invalid presets
idsp_room = bound( 0, idsp_room, MAX_ROOM_TYPES );
if( FBitSet( hisound.flags, FCVAR_CHANGED ))
if( FBitSet( hisound->flags, FCVAR_CHANGED ))
{
sxhires = hisound.value;
ClearBits( hisound.flags, FCVAR_CHANGED );
sxhires = hisound->value;
ClearBits( hisound->flags, FCVAR_CHANGED );
}
if( idsp_room == room_typeprev && idsp_room == 0 )
@@ -891,15 +898,15 @@ void CheckNewDspPresets( void )
cur = ptable + idsp_room;
Cvar_DirectSetValue( &sxmod_lowpass, cur->room_lp );
Cvar_DirectSetValue( &sxmod_mod, cur->room_mod );
Cvar_DirectSetValue( &sxrvb_size, cur->room_size );
Cvar_DirectSetValue( &sxrvb_feedback, cur->room_refl );
Cvar_DirectSetValue( &sxrvb_lp, cur->room_rvblp );
Cvar_DirectSetValue( &sxdly_delay, cur->room_delay );
Cvar_DirectSetValue( &sxdly_feedback, cur->room_feedback );
Cvar_DirectSetValue( &sxdly_lp, cur->room_dlylp );
Cvar_DirectSetValue( &sxste_delay, cur->room_left );
Cvar_SetValue( "room_lp", cur->room_lp );
Cvar_SetValue( "room_mod", cur->room_mod );
Cvar_SetValue( "room_size", cur->room_size );
Cvar_SetValue( "room_refl", cur->room_refl );
Cvar_SetValue( "room_rvblp", cur->room_rvblp );
Cvar_SetValue( "room_delay", cur->room_delay );
Cvar_SetValue( "room_feedback", cur->room_feedback );
Cvar_SetValue( "room_dlylp", cur->room_dlylp );
Cvar_SetValue( "room_left", cur->room_left );
}
room_typeprev = idsp_room;
@@ -908,15 +915,15 @@ void CheckNewDspPresets( void )
DLY_CheckNewDelayVal( );
DLY_CheckNewStereoDelayVal();
ClearBits( sxrvb_size.flags, FCVAR_CHANGED );
ClearBits( sxdly_delay.flags, FCVAR_CHANGED );
ClearBits( sxste_delay.flags, FCVAR_CHANGED );
ClearBits( sxrvb_size->flags, FCVAR_CHANGED );
ClearBits( sxdly_delay->flags, FCVAR_CHANGED );
ClearBits( sxste_delay->flags, FCVAR_CHANGED );
}
static void SX_Profiling_f( void )
void SX_Profiling_f( void )
{
portable_samplepair_t testbuffer[512];
float oldroom = room_type.value;
float oldroom = room_type->value;
double start, end;
int i, calls;
@@ -928,7 +935,7 @@ static void SX_Profiling_f( void )
if( Cmd_Argc() > 1 )
{
Cvar_DirectSetValue( &room_type, Q_atof( Cmd_Argv( 1 )));
Cvar_SetValue( "room_type", Q_atof( Cmd_Argv( 1 )));
SX_ReloadRoomFX();
CheckNewDspPresets(); // we just need idsp_room immediately, for message below
}
@@ -938,7 +945,7 @@ static void SX_Profiling_f( void )
start = Sys_DoubleTime();
for( calls = 10000; calls; calls-- )
{
DSP_Process( testbuffer, 512 );
DSP_Process( idsp_room, testbuffer, 512 );
}
end = Sys_DoubleTime();
@@ -946,7 +953,7 @@ static void SX_Profiling_f( void )
if( Cmd_Argc() > 1 )
{
Cvar_DirectSetValue( &room_type, oldroom );
Cvar_SetValue( "room_type", oldroom );
SX_ReloadRoomFX();
CheckNewDspPresets();
}

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 );
@@ -158,7 +155,7 @@ wavdata_t *S_LoadSound( sfx_t *sfx )
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, SOUND_RESAMPLE );
else if( sc->rate > SOUND_22k && sc->rate < SOUND_44k ) // some bad sounds
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

@@ -64,12 +64,6 @@ float S_GetMasterVolume( 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 && soundfade.percent != 0 )
{
scale = bound( 0.0f, soundfade.percent / 100.0f, 1.0f );
@@ -97,7 +91,7 @@ void S_FadeClientVolume( float fadePercent, float fadeOutSeconds, float holdTime
S_IsClient
=================
*/
static qboolean S_IsClient( int entnum )
qboolean S_IsClient( int entnum )
{
return ( entnum == s_listener.entnum );
}
@@ -130,7 +124,7 @@ void S_FreeChannel( channel_t *ch )
S_UpdateSoundFade
=================
*/
static void S_UpdateSoundFade( void )
void S_UpdateSoundFade( void )
{
float f, totaltime, elapsed;
@@ -190,7 +184,7 @@ override any other sound playing on the same channel (see code comments below fo
exceptions).
=================
*/
static qboolean SND_FStreamIsPlaying( sfx_t *sfx )
qboolean SND_FStreamIsPlaying( sfx_t *sfx )
{
int ch_idx;
@@ -328,7 +322,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 +376,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;
}
@@ -405,7 +399,7 @@ returns TRUE if sound was altered,
returns FALSE if sound was not found (sound is not playing)
=================
*/
static int S_AlterChannel( int entnum, int channel, sfx_t *sfx, int vol, int pitch, int flags )
int S_AlterChannel( int entnum, int channel, sfx_t *sfx, int vol, int pitch, int flags )
{
channel_t *ch;
int i;
@@ -463,7 +457,7 @@ static int S_AlterChannel( int entnum, int channel, sfx_t *sfx, int vol, int pit
S_SpatializeChannel
=================
*/
static void S_SpatializeChannel( int *left_vol, int *right_vol, int master_vol, float gain, float dot, float dist )
void S_SpatializeChannel( int *left_vol, int *right_vol, int master_vol, float gain, float dot, float dist )
{
float lscale, rscale, scale;
@@ -486,7 +480,7 @@ static void S_SpatializeChannel( int *left_vol, int *right_vol, int master_vol,
SND_Spatialize
=================
*/
static void SND_Spatialize( channel_t *ch )
void SND_Spatialize( channel_t *ch )
{
vec3_t source_vec;
float dist, dot, gain = 1.0f;
@@ -503,7 +497,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 )
@@ -641,7 +635,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 )
@@ -654,6 +648,20 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
// Init client entity mouth movement vars
SND_InitMouth( ent, chan );
for( ch_idx = NUM_AMBIENTS, check = channels + NUM_AMBIENTS; ch_idx < MAX_DYNAMIC_CHANNELS; ch_idx++, check++)
{
if( check == target_chan ) continue;
if( check->sfx == sfx && !check->pMixer.sample )
{
// skip up to 0.1 seconds of audio
int skip = COM_RandomLong( 0, (long)( 0.1f * check->sfx->cache->rate ));
S_SetSampleStart( check, sfx->cache, skip );
break;
}
}
}
/*
@@ -893,7 +901,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;
@@ -928,7 +936,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
@@ -959,7 +967,7 @@ int S_GetCurrentDynamicSounds( soundlist_t *pout, int size )
S_InitAmbientChannels
===================
*/
static void S_InitAmbientChannels( void )
void S_InitAmbientChannels( void )
{
int ambient_channel;
channel_t *chan;
@@ -981,7 +989,7 @@ static void S_InitAmbientChannels( void )
S_UpdateAmbientSounds
===================
*/
static void S_UpdateAmbientSounds( void )
void S_UpdateAmbientSounds( void )
{
mleaf_t *leaf;
float vol;
@@ -1413,7 +1421,7 @@ static void S_FreeRawChannels( void )
S_ClearBuffer
==================
*/
static void S_ClearBuffer( void )
void S_ClearBuffer( void )
{
S_ClearRawChannels();
@@ -1512,7 +1520,7 @@ static int S_GetSoundtime( void )
}
//=============================================================================
static void S_UpdateChannels( void )
void S_UpdateChannels( void )
{
uint endtime;
int samps;
@@ -1599,10 +1607,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
@@ -1700,7 +1709,7 @@ console functions
===============================================================================
*/
static void S_Play_f( void )
void S_Play_f( void )
{
if( Cmd_Argc() == 1 )
{
@@ -1711,7 +1720,7 @@ static void S_Play_f( void )
S_StartLocalSound( Cmd_Argv( 1 ), VOL_NORM, false );
}
static void S_Play2_f( void )
void S_Play2_f( void )
{
int i = 1;
@@ -1728,7 +1737,7 @@ static void S_Play2_f( void )
}
}
static void S_PlayVol_f( void )
void S_PlayVol_f( void )
{
if( Cmd_Argc() == 1 )
{
@@ -1754,7 +1763,7 @@ static void S_Say( const char *name, qboolean reliable )
S_StartLocalSound( sentence, 1.0f, reliable );
}
static void S_Say_f( void )
void S_Say_f( void )
{
if( Cmd_Argc() == 1 )
{
@@ -1765,7 +1774,7 @@ static void S_Say_f( void )
S_Say( Cmd_Argv( 1 ), false );
}
static void S_SayReliable_f( void )
void S_SayReliable_f( void )
{
if( Cmd_Argc() == 1 )
{
@@ -1781,7 +1790,7 @@ static void S_SayReliable_f( void )
S_Music_f
=================
*/
static void S_Music_f( void )
void S_Music_f( void )
{
int c = Cmd_Argc();
@@ -1845,7 +1854,7 @@ static void S_Music_f( void )
S_StopSound_f
=================
*/
static void S_StopSound_f( void )
void S_StopSound_f( void )
{
S_StopAllSounds( true );
}
@@ -1855,7 +1864,7 @@ static void S_StopSound_f( void )
S_SoundFade_f
=================
*/
static void S_SoundFade_f( void )
void S_SoundFade_f( void )
{
int c = Cmd_Argc();
float fadeTime = 5.0f;
@@ -1889,7 +1898,7 @@ void S_SoundInfo_f( void )
S_VoiceRecordStart_f
=================
*/
static void S_VoiceRecordStart_f( void )
void S_VoiceRecordStart_f( void )
{
if( cls.state != ca_active || cls.legacymode )
return;
@@ -1902,7 +1911,7 @@ static void S_VoiceRecordStart_f( void )
S_VoiceRecordStop_f
=================
*/
static void S_VoiceRecordStop_f( void )
void S_VoiceRecordStop_f( void )
{
if( cls.state != ca_active || !Voice_IsRecording() )
return;

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;
@@ -84,7 +58,7 @@ S_TransferPaintBuffer
===================
*/
static void S_TransferPaintBuffer( int endtime )
void S_TransferPaintBuffer( int endtime )
{
int *snd_p, snd_linear_count;
int lpos, lpaintedtime;
@@ -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];
@@ -227,7 +201,7 @@ CHANNEL MIXING
===============================================================================
*/
static void S_PaintMonoFrom8( portable_samplepair_t *pbuf, int *volume, byte *pData, int outCount )
void S_PaintMonoFrom8( portable_samplepair_t *pbuf, int *volume, byte *pData, int outCount )
{
int *lscale, *rscale;
int i, data;
@@ -243,7 +217,7 @@ static void S_PaintMonoFrom8( portable_samplepair_t *pbuf, int *volume, byte *pD
}
}
static void S_PaintStereoFrom8( portable_samplepair_t *pbuf, int *volume, byte *pData, int outCount )
void S_PaintStereoFrom8( portable_samplepair_t *pbuf, int *volume, byte *pData, int outCount )
{
int *lscale, *rscale;
uint left, right;
@@ -263,7 +237,7 @@ static void S_PaintStereoFrom8( portable_samplepair_t *pbuf, int *volume, byte *
}
}
static void S_PaintMonoFrom16( portable_samplepair_t *pbuf, int *volume, short *pData, int outCount )
void S_PaintMonoFrom16( portable_samplepair_t *pbuf, int *volume, short *pData, int outCount )
{
int left, right;
int i, data;
@@ -278,7 +252,7 @@ static void S_PaintMonoFrom16( portable_samplepair_t *pbuf, int *volume, short *
}
}
static void S_PaintStereoFrom16( portable_samplepair_t *pbuf, int *volume, short *pData, int outCount )
void S_PaintStereoFrom16( portable_samplepair_t *pbuf, int *volume, short *pData, int outCount )
{
uint *data;
int left, right;
@@ -299,11 +273,11 @@ static void S_PaintStereoFrom16( portable_samplepair_t *pbuf, int *volume, short
}
}
static void S_Mix8MonoTimeCompress( portable_samplepair_t *pbuf, int *volume, byte *pData, int inputOffset, uint rateScale, int outCount, int timecompress )
void S_Mix8MonoTimeCompress( portable_samplepair_t *pbuf, int *volume, byte *pData, int inputOffset, uint rateScale, int outCount, int timecompress )
{
}
static void S_Mix8Mono( portable_samplepair_t *pbuf, int *volume, byte *pData, int inputOffset, uint rateScale, int outCount, int timecompress )
void S_Mix8Mono( portable_samplepair_t *pbuf, int *volume, byte *pData, int inputOffset, uint rateScale, int outCount, int timecompress )
{
int i, sampleIndex = 0;
uint sampleFrac = inputOffset;
@@ -335,7 +309,7 @@ static void S_Mix8Mono( portable_samplepair_t *pbuf, int *volume, byte *pData, i
}
}
static void S_Mix8Stereo( portable_samplepair_t *pbuf, int *volume, byte *pData, int inputOffset, uint rateScale, int outCount )
void S_Mix8Stereo( portable_samplepair_t *pbuf, int *volume, byte *pData, int inputOffset, uint rateScale, int outCount )
{
int i, sampleIndex = 0;
uint sampleFrac = inputOffset;
@@ -361,7 +335,7 @@ static void S_Mix8Stereo( portable_samplepair_t *pbuf, int *volume, byte *pData,
}
}
static void S_Mix16Mono( portable_samplepair_t *pbuf, int *volume, short *pData, int inputOffset, uint rateScale, int outCount )
void S_Mix16Mono( portable_samplepair_t *pbuf, int *volume, short *pData, int inputOffset, uint rateScale, int outCount )
{
int i, sampleIndex = 0;
uint sampleFrac = inputOffset;
@@ -383,7 +357,7 @@ static void S_Mix16Mono( portable_samplepair_t *pbuf, int *volume, short *pData,
}
}
static void S_Mix16Stereo( portable_samplepair_t *pbuf, int *volume, short *pData, int inputOffset, uint rateScale, int outCount )
void S_Mix16Stereo( portable_samplepair_t *pbuf, int *volume, short *pData, int inputOffset, uint rateScale, int outCount )
{
int i, sampleIndex = 0;
uint sampleFrac = inputOffset;
@@ -405,7 +379,7 @@ static void S_Mix16Stereo( portable_samplepair_t *pbuf, int *volume, short *pDat
}
}
static void S_MixChannel( channel_t *pChannel, void *pData, int outputOffset, int inputOffset, uint fracRate, int outCount, int timecompress )
void S_MixChannel( channel_t *pChannel, void *pData, int outputOffset, int inputOffset, uint fracRate, int outCount, int timecompress )
{
int pvol[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
@@ -522,7 +496,7 @@ int S_MixDataToDevice( channel_t *pChannel, int sampleCount, int outRate, int ou
return outOffset - startingOffset;
}
static qboolean S_ShouldContinueMixing( channel_t *ch )
qboolean S_ShouldContinueMixing( channel_t *ch )
{
if( ch->isSentence )
{
@@ -543,13 +517,12 @@ static qboolean S_ShouldContinueMixing( channel_t *ch )
// this routine will fill the paintbuffer to endtime. Otherwise, fewer samples are mixed.
// if( endtime - paintedtime ) is not aligned on boundaries of 4,
// we'll miss data if outputRate < SOUND_DMA_SPEED!
static void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate )
void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate )
{
channel_t *ch;
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]));
@@ -675,7 +647,7 @@ static portable_samplepair_t *S_GetNextpFilter( int i, portable_samplepair_t *pb
// if NULL then perform no filtering.
// count: how many samples to upsample. will become count*2 samples in buffer, in place.
static void S_Interpolate2xCubic( portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem, int cfltmem, int count )
void S_Interpolate2xCubic( portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem, int cfltmem, int count )
{
// implement cubic interpolation on 2x upsampled buffer. Effectively delays buffer contents by 2 samples.
@@ -768,7 +740,7 @@ static void S_Interpolate2xCubic( portable_samplepair_t *pbuffer, portable_sampl
// prevfilter: filter memory. NOTE: this must match the filtertype ie: filterlinear[] for FILTERTYPE_LINEAR
// if NULL then perform no filtering.
// count: how many samples to upsample. will become count*2 samples in buffer, in place.
static void S_Interpolate2xLinear( portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem, int cfltmem, int count )
void S_Interpolate2xLinear( portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem, int cfltmem, int count )
{
int i, upCount = count<<1;
@@ -797,7 +769,7 @@ static void S_Interpolate2xLinear( portable_samplepair_t *pbuffer, portable_samp
// if NULL then perform no filtering.
// cfltmem: max number of sample pairs filter can use
// filtertype: FILTERTYPE_NONE, _LINEAR, _CUBIC etc. Must match prevfilter.
static void S_MixBufferUpsample2x( int count, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem, int cfltmem, int filtertype )
void S_MixBufferUpsample2x( int count, portable_samplepair_t *pbuffer, portable_samplepair_t *pfiltermem, int cfltmem, int filtertype )
{
int upCount = count<<1;
int i, j;
@@ -850,7 +822,7 @@ void MIX_ClearAllPaintBuffers( int SampleCount, qboolean clearFilters )
// mixes pbuf1 + pbuf2 into pbuf3, count samples
// fgain is output gain 0-1.0
// NOTE: pbuf3 may equal pbuf1 or pbuf2!
static void MIX_MixPaintbuffers( int ibuf1, int ibuf2, int ibuf3, int count, float fgain )
void MIX_MixPaintbuffers( int ibuf1, int ibuf2, int ibuf3, int count, float fgain )
{
portable_samplepair_t *pbuf1, *pbuf2, *pbuf3;
int i, gain;
@@ -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:
@@ -891,7 +855,7 @@ static void MIX_MixPaintbuffers( int ibuf1, int ibuf2, int ibuf3, int count, flo
}
}
static void MIX_CompressPaintbuffer( int ipaint, int count )
void MIX_CompressPaintbuffer( int ipaint, int count )
{
portable_samplepair_t *pbuf;
paintbuffer_t *ppaint;
@@ -907,7 +871,7 @@ static void MIX_CompressPaintbuffer( int ipaint, int count )
}
}
static void S_MixUpsample( int sampleCount, int filtertype )
void S_MixUpsample( int sampleCount, int filtertype )
{
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
int ifilter = ppaint->ifilter;
@@ -920,7 +884,7 @@ static void S_MixUpsample( int sampleCount, int filtertype )
ppaint->ifilter++;
}
static void MIX_MixRawSamplesBuffer( int end )
void MIX_MixRawSamplesBuffer( int end )
{
portable_samplepair_t *pbuf, *roombuf, *streambuf;
uint i, j, stop;
@@ -964,7 +928,7 @@ static void MIX_MixRawSamplesBuffer( int end )
// IROOMBUFFER, IFACINGBUFFER, IFACINGAWAY
// dsp fx are then applied to these buffers by the caller.
// caller also remixes all into final IPAINTBUFFER output.
static void MIX_UpsampleAllPaintbuffers( int end, int count )
void MIX_UpsampleAllPaintbuffers( int end, int count )
{
// 11khz sounds are mixed into 3 buffers based on distance from listener, and facing direction
// These buffers are facing, facingaway, room
@@ -1035,8 +999,7 @@ void MIX_PaintChannels( int endtime )
MIX_UpsampleAllPaintbuffers( end, count );
// process all sounds with DSP
if( cls.key_dest != key_menu )
DSP_Process( MIX_GetPFrontFromIPaint( IROOMBUFFER ), count );
DSP_Process( idsp_room, MIX_GetPFrontFromIPaint( IROOMBUFFER ), count );
// add music or soundtrack from movie (no dsp)
MIX_MixPaintbuffers( IPAINTBUFFER, IROOMBUFFER, IPAINTBUFFER, count, S_GetMasterVolume() );

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 );
@@ -102,7 +96,6 @@ void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, int
// open stream
s_bgTrack.stream = FS_OpenStream( introTrack );
Q_strncpy( s_bgTrack.current, introTrack, sizeof( s_bgTrack.current ));
memset( &musicfade, 0, sizeof( musicfade )); // clear any soundfade
s_bgTrack.source = cls.key_dest;
@@ -148,7 +141,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 +149,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

@@ -16,6 +16,204 @@ GNU General Public License for more details.
#include "common.h"
#include "sound.h"
// hardcoded macros to test for zero crossing
#define ZERO_X_8( b ) (( b ) < 2 && ( b ) > -2 )
#define ZERO_X_16( b ) (( b ) < 512 && ( b ) > -512 )
//-----------------------------------------------------------------------------
// Purpose: Search backward for a zero crossing starting at sample
// Input : sample - starting point
// Output : position of zero crossing
//-----------------------------------------------------------------------------
int S_ZeroCrossingBefore( wavdata_t *pWaveData, int sample )
{
if( pWaveData == NULL )
return sample;
if( pWaveData->type == WF_PCMDATA )
{
int sampleSize;
sampleSize = pWaveData->width * pWaveData->channels;
// this can never be zero -- other functions divide by this.
// This should never happen, but avoid crashing
if( sampleSize <= 0 ) sampleSize = 1;
if( pWaveData->width == 1 )
{
signed char *pData = (signed char *)(pWaveData->buffer + sample * sampleSize);
qboolean zero = false;
if( pWaveData->channels == 1 )
{
while( sample > 0 && !zero )
{
if( ZERO_X_8( *pData ))
{
zero = true;
}
else
{
sample--;
pData--;
}
}
}
else
{
while( sample > 0 && !zero )
{
if( ZERO_X_8( *pData ) && ZERO_X_8( pData[1] ))
{
zero = true;
}
else
{
sample--;
pData--;
}
}
}
}
else
{
short *pData = (short *)(pWaveData->buffer + sample * sampleSize);
qboolean zero = false;
if( pWaveData->channels == 1 )
{
while( sample > 0 && !zero )
{
if( ZERO_X_16(*pData ))
{
zero = true;
}
else
{
pData--;
sample--;
}
}
}
else
{
while( sample > 0 && !zero )
{
if( ZERO_X_16( *pData ) && ZERO_X_16( pData[1] ))
{
zero = true;
}
else
{
sample--;
pData--;
}
}
}
}
}
return sample;
}
//-----------------------------------------------------------------------------
// Purpose: Search forward for a zero crossing
// Input : sample - starting point
// Output : position of found zero crossing
//-----------------------------------------------------------------------------
int S_ZeroCrossingAfter( wavdata_t *pWaveData, int sample )
{
if( pWaveData == NULL )
return sample;
if( pWaveData->type == WF_PCMDATA )
{
int sampleSize;
sampleSize = pWaveData->width * pWaveData->channels;
// this can never be zero -- other functions divide by this.
// This should never happen, but avoid crashing
if( sampleSize <= 0 ) sampleSize = 1;
if( pWaveData->width == 1 ) // 8-bit
{
signed char *pData = (signed char *)(pWaveData->buffer + sample * sampleSize);
qboolean zero = false;
if( pWaveData->channels == 1 )
{
while( sample < pWaveData->samples && !zero )
{
if( ZERO_X_8( *pData ))
{
zero = true;
}
else
{
sample++;
pData++;
}
}
}
else
{
while( sample < pWaveData->samples && !zero )
{
if( ZERO_X_8( *pData ) && ZERO_X_8( pData[1] ))
{
zero = true;
}
else
{
sample++;
pData++;
}
}
}
}
else
{
short *pData = (short *)(pWaveData->buffer + sample * sampleSize);
qboolean zero = false;
if( pWaveData->channels == 1 )
{
while( sample > 0 && !zero )
{
if( ZERO_X_16( *pData ))
{
zero = true;
}
else
{
pData++;
sample++;
}
}
}
else
{
while( sample > 0 && !zero )
{
if( ZERO_X_16( *pData ) && ZERO_X_16( pData[1] ))
{
zero = true;
}
else
{
sample++;
pData++;
}
}
}
}
}
return sample;
}
//-----------------------------------------------------------------------------
// Purpose: wrap the position wrt looping
// Input : samplePosition - absolute position
@@ -27,7 +225,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;
@@ -81,3 +279,28 @@ int S_GetOutputData( wavdata_t *pSource, void **pData, int samplePosition, int s
return sampleCount;
}
// move the current position to newPosition
void S_SetSampleStart( channel_t *pChan, wavdata_t *pSource, int newPosition )
{
if( pSource )
newPosition = S_ZeroCrossingAfter( pSource, newPosition );
pChan->pMixer.sample = newPosition;
}
// end playback at newEndPosition
void S_SetSampleEnd( channel_t *pChan, wavdata_t *pSource, int newEndPosition )
{
// forced end of zero means play the whole sample
if( !newEndPosition ) newEndPosition = 1;
if( pSource )
newEndPosition = S_ZeroCrossingBefore( pSource, newEndPosition );
// past current position? limit.
if( newEndPosition < pChan->pMixer.sample )
newEndPosition = pChan->pMixer.sample;
pChan->pMixer.forcedEndSample = newEndPosition;
}

View File

@@ -16,128 +16,13 @@ GNU General Public License for more details.
#include "common.h"
#include "sound.h"
#include "const.h"
#include "sequence.h"
#include <ctype.h>
#define TRIM_SCAN_MAX 255
#define TRIM_SAMPLES_BELOW_8 2
#define TRIM_SAMPLES_BELOW_16 512 // 65k * 2 / 256
#define CVOXFILESENTENCEMAX 4096
static int cszrawsentences = 0;
static char *rgpszrawsentence[CVOXFILESENTENCEMAX];
static const char *voxperiod = "_period", *voxcomma = "_comma";
static qboolean S_ShouldTrimSample8( const int8_t *buf, int channels )
{
if( abs( buf[0] ) > TRIM_SAMPLES_BELOW_8 )
return false;
if( channels >= 2 && abs( buf[1] ) > TRIM_SAMPLES_BELOW_8 )
return false;
return true;
}
static qboolean S_ShouldTrimSample16( const int16_t *buf, int channels )
{
if( abs( buf[0] ) > TRIM_SAMPLES_BELOW_16 )
return false;
if( channels >= 2 && abs( buf[1] ) > TRIM_SAMPLES_BELOW_16 )
return false;
return true;
}
static int S_TrimStart( const wavdata_t *wav, int start )
{
size_t channels = wav->channels, width = wav->width, i;
if( wav->type != WF_PCMDATA )
return start;
if( width == 1 )
{
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * start];
for( i = 0; i < TRIM_SCAN_MAX && start < wav->samples; i++ )
{
if( !S_ShouldTrimSample8( data, wav->channels ))
break;
start += channels;
data += channels;
}
}
else if( width == 2 )
{
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * start];
for( i = 0; i < TRIM_SCAN_MAX && start < wav->samples; i++ )
{
if( !S_ShouldTrimSample16( data, wav->channels ))
break;
start += channels;
data += channels;
}
}
return start;
}
static int S_TrimEnd( const wavdata_t *wav, int end )
{
size_t channels = wav->channels, width = wav->width, i;
if( wav->type != WF_PCMDATA )
return end;
if( width == 1 )
{
const int8_t *data = (const int8_t *)&wav->buffer[channels * width * end];
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
{
if( !S_ShouldTrimSample8( data, wav->channels ))
break;
end -= channels;
data -= channels;
}
}
else if( width == 2 )
{
const int16_t *data = (const int16_t *)&wav->buffer[channels * width * end];
for( i = 0; i < TRIM_SCAN_MAX && end > 0; i++ )
{
if( !S_ShouldTrimSample16( data, wav->channels ))
break;
end -= channels;
data -= channels;
}
}
return end;
}
static void S_TrimStartEndTimes( channel_t *ch, wavdata_t *wav, int start, int end )
{
ch->pMixer.sample = start = S_TrimStart( wav, start );
// don't overrun the buffer while trimming end
if( end == 0 )
end = wav->samples - wav->channels;
if( end < start )
end = start;
ch->pMixer.forcedEndSample = S_TrimEnd( wav, end );
}
// return number of samples mixed
int VOX_MixDataToDevice( channel_t *pchan, int sampleCount, int outputRate, int outputOffset )
{
@@ -194,7 +79,11 @@ void VOX_LoadWord( channel_t *ch )
if( end <= start ) end = 0;
S_TrimStartEndTimes( ch, data, start * 0.01f * samples, end * 0.01f * samples );
if( start )
S_SetSampleStart( ch, data, start * 0.01f * samples );
if( end )
S_SetSampleEnd( ch, data, end * 0.01f * samples );
}
void VOX_FreeWord( channel_t *ch )
@@ -261,7 +150,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;
}
@@ -276,11 +165,24 @@ static const char *VOX_LookupString( const char *pszin )
int i = -1, len;
const char *c;
// check if we are an immediate sentence
// check if we are a CSCZ or immediate sentence
if( *pszin == '#' )
{
// immediate sentence, probably coming from "speak" command
return pszin + 1;
// Q_atoi is too smart and allows negative values
// so check with Q_isdigit beforehand
if( Q_isdigit( pszin + 1 ))
{
sentenceEntry_s *sentenceEntry;
i = Q_atoi( pszin + 1 );
if(( sentenceEntry = Sequence_GetSentenceByIndex( i )))
return sentenceEntry->data;
return NULL;
}
else
{
// immediate sentence, probably coming from "speak" command
return pszin + 1;
}
}
// check if we received an index
@@ -467,7 +369,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;
}
@@ -475,13 +377,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;
}

View File

@@ -20,181 +20,210 @@ 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[1]; // 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 *dsp_off;
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;
extern convar_t s_warn_late_precache;
void S_InitScaletable( void );
wavdata_t *S_LoadSound( sfx_t *sfx );
@@ -227,7 +256,8 @@ void S_InitSounds( void );
void SX_Init( void );
void SX_Free( void );
void CheckNewDspPresets( void );
void DSP_Process( portable_samplepair_t *pbfront, int sampleCount );
void DSP_Process( int idsp, portable_samplepair_t *pbfront, int sampleCount );
float DSP_GetGain( int idsp );
void DSP_ClearState( void );
qboolean S_Init( void );
@@ -265,6 +295,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 );
@@ -275,6 +306,8 @@ int S_ZeroCrossingAfter( wavdata_t *pWaveData, int sample );
int S_ZeroCrossingBefore( wavdata_t *pWaveData, int sample );
int S_ConvertLoopedPosition( wavdata_t *pSource, int samplePosition, qboolean use_loop );
int S_GetOutputData( wavdata_t *pSource, void **pData, int samplePosition, int sampleCount, qboolean use_loop );
void S_SetSampleStart( channel_t *pChan, wavdata_t *pSource, int newPosition );
void S_SetSampleEnd( channel_t *pChan, wavdata_t *pSource, int newEndPosition );
//
// s_vox.c

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,180 +23,30 @@ 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_support_interface_t dllFuncs;
VGUI_DefaultCursor cursor;
vguiapi_t dllFuncs;
int textures[VGUI_MAX_TEXTURES];
int texture_id;
int bound_texture;
byte color[4];
qboolean enable_texture;
HINSTANCE hInstance;
enum VGUI_KeyCode virtualKeyTrans[256];
} vgui_static_t;
static vgui_static_t vgui = {
false, -1
} vgui =
{
false,
{ 0 }, // not initialized yet
-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 ));
vgui.texture_id = vgui.bound_texture = 0;
}
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 )
{
@@ -242,27 +92,21 @@ qboolean VGui_IsActive( void )
return vgui.initialized;
}
void VGui_RegisterCvars( void )
static vgui_support_api_t gEngfuncs =
{
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,
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,
@@ -273,59 +117,171 @@ static const vguiapi_t gEngfuncs =
Platform_GetClipboardText,
Platform_SetClipboardText,
Platform_GetKeyModifiers,
COM_LoadLibrary,
COM_FreeLibrary,
COM_GetProcAddress,
};
static void VGui_FillAPIFromRef( vgui_support_api_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 HINSTANCE VGui_LoadSupportLibrary( void )
{
string vguiloader;
string vguilib;
HINSTANCE hInstance;
// HACKHACK: try to load path from custom path
// to support having different versions of VGUI
if( Sys_GetParmFromCmdLine( "-vguilib", vguilib ) && !COM_LoadLibrary( vguilib, false, false ))
{
Con_Reportf( S_WARN "VGUI preloading failed. Default library will be used! Reason: %s", COM_GetLibraryError());
}
if( !Sys_GetParmFromCmdLine( "-vguiloader", vguiloader ))
{
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, sizeof( vguiloader ));
}
hInstance = COM_LoadLibrary( vguiloader, false, false );
if( !hInstance )
{
if( FS_FileExists( vguiloader, false ))
Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() );
else Con_Reportf( "vgui_support: not found\n" );
}
return hInstance;
}
static qboolean VGui_ProbeNewAPI( HINSTANCE hInstance,
vgui_support_interface_t *iface, const vgui_support_api_t *api )
{
const int version = VGUI_SUPPORT_API_VERSION;
static vgui_support_api_t localapi;
VGUISUPPORTAPI F;
F = COM_GetProcAddress( hInstance, GET_VGUI_SUPPORT_API );
if( !F )
return false;
// keep local temporary copy, do not let vgui_support to mess up here
memcpy( &localapi, api, sizeof( localapi ));
if( F( version, iface, &localapi ) != version )
return false;
Con_Reportf( "vgui_support: initialized new API\n" );
return true;
}
static qboolean VGui_ProbeOldAPI( HINSTANCE hInstance,
vgui_support_interface_t *iface, const vgui_support_api_t *api,
qboolean client )
{
static legacy_vguiapi_t localapi;
LEGACY_VGUISUPPORTAPI F;
F = COM_GetProcAddress( hInstance, client ? LEGACY_CLIENT_GET_VGUI_SUPPORT_API : LEGACY_GET_VGUI_SUPPORT_API );
if( !F )
return false;
memset( &localapi, 0, sizeof( localapi ));
localapi.DrawInit = api->DrawInit;
localapi.DrawShutdown = api->DrawShutdown;
localapi.SetupDrawingText = api->SetupDrawingText;
localapi.SetupDrawingRect = api->SetupDrawingRect;
localapi.SetupDrawingImage = api->SetupDrawingImage;
localapi.BindTexture = api->BindTexture;
localapi.EnableTexture = api->EnableTexture;
localapi.CreateTexture = api->CreateTexture;
localapi.UploadTexture = api->UploadTexture;
localapi.UploadTextureBlock = api->UploadTextureBlock;
localapi.DrawQuad = api->DrawQuad;
localapi.GetTextureSizes = api->GetTextureSizes;
localapi.GenerateTexture = api->GenerateTexture;
localapi.EngineMalloc = api->EngineMalloc;
localapi.CursorSelect = api->CursorSelect;
localapi.GetColor = api->GetColor;
localapi.IsInGame = api->IsInGame;
localapi.EnableTextInput = api->EnableTextInput;
localapi.GetCursorPos = api->GetCursorPos;
localapi.ProcessUtfChar = api->ProcessUtfChar;
localapi.GetClipboardText = api->GetClipboardText;
localapi.SetClipboardText = api->SetClipboardText;
localapi.GetKeyModifiers = api->GetKeyModifiers;
F( &localapi );
localapi.initialized = true;
iface->Startup = localapi.Startup;
iface->Shutdown = localapi.Shutdown;
iface->GetPanel = localapi.GetPanel;
iface->Paint = localapi.Paint;
iface->Mouse = localapi.Mouse;
iface->Key = localapi.Key;
iface->MouseMove = localapi.MouseMove;
iface->TextInput = localapi.TextInput;
Con_Reportf( "vgui_support: initialized legacy API in %s module\n", client ? "client" : "support" );
return true;
}
qboolean VGui_LoadProgs( HINSTANCE hInstance )
{
void (*F)( vguiapi_t* );
LEGACY_VGUISUPPORTAPI F;
qboolean client = hInstance != NULL;
memcpy( &vgui.dllFuncs, &gEngfuncs, sizeof( vgui.dllFuncs ));
// not loading interface from client.dll, load vgui_support.dll instead
if( !client )
{
string vguiloader, vguilib;
hInstance = vgui.hInstance = VGui_LoadSupportLibrary();
// HACKHACK: try to load path from custom path
// to support having different versions of VGUI
if( Sys_GetParmFromCmdLine( "-vguilib", vguilib ) && !COM_LoadLibrary( vguilib, false, false ))
if( !hInstance )
return false;
}
// prepare api funcs
VGui_FillAPIFromRef( &gEngfuncs, &ref.dllFuncs );
// try new API first
if( !VGui_ProbeNewAPI( vgui.hInstance, &vgui.dllFuncs, &gEngfuncs ))
{
// try legacy API next
if( !VGui_ProbeOldAPI( vgui.hInstance, &vgui.dllFuncs, &gEngfuncs, client ))
{
Con_Reportf( S_WARN "VGUI preloading failed. Default library will be used! Reason: %s", COM_GetLibraryError());
}
if( !Sys_GetParmFromCmdLine( "-vguiloader", vguiloader ))
{
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, sizeof( vguiloader ));
}
hInstance = vgui.hInstance = COM_LoadLibrary( vguiloader, false, false );
if( !vgui.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__ );
Con_Reportf( S_ERROR "Failed to find VGUI support API entry point in %s module\n", client ? "client" : "support" );
return false;
}
}
// try legacy API first
F = COM_GetProcAddress( hInstance, client ? "InitVGUISupportAPI" : "InitAPI" );
if( F )
{
F( &vgui.dllFuncs );
vgui.initialized = vgui.dllFuncs.initialized = true;
Con_Reportf( "%s: initialized legacy API in %s module\n", __func__, 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" );
return false;
vgui.initialized = true;
return true;
}
/*
@@ -334,7 +290,7 @@ VGui_Startup
================
*/
void VGui_Startup( int width, int height )
void VGui_Startup( HINSTANCE clientInstance, int width, int height )
{
// vgui not initialized from both support and client modules, skip
if( !vgui.initialized )
@@ -349,12 +305,18 @@ void VGui_Startup( int width, int height )
else if( width <= 1280 ) width = 1280;
else if( width <= 1600 ) width = 1600;
if( vgui.dllFuncs.Startup )
vgui.dllFuncs.Startup( width, height );
if( !clientInstance )
{
if( vgui.dllFuncs.Startup )
vgui.dllFuncs.Startup( width, height );
}
else
{
if( vgui.dllFuncs.ClientStartup )
vgui.dllFuncs.ClientStartup( clientInstance, width, height );
}
}
/*
================
VGui_Shutdown
@@ -370,9 +332,8 @@ void VGui_Shutdown( void )
if( vgui.hInstance )
COM_FreeLibrary( vgui.hInstance );
// drop pointers to now unloaded vgui_support
memcpy( &vgui.dllFuncs, &gEngfuncs, sizeof( vgui.dllFuncs ));
vgui.hInstance = NULL;
vgui.initialized = false;
}

View File

@@ -21,7 +21,7 @@ GNU General Public License for more details.
//
void VGui_RegisterCvars( void );
qboolean VGui_LoadProgs( HINSTANCE hInstance );
void VGui_Startup( int width, int height );
void VGui_Startup( HINSTANCE clientInstance, int width, int height );
void VGui_Shutdown( void );
void VGui_Paint( void );
void VGui_RunFrame( void );

View File

@@ -20,20 +20,34 @@ GNU General Public License for more details.
#include "vid_common.h"
#include "platform/platform.h"
static CVAR_DEFINE_AUTO( vid_mode, "0", FCVAR_RENDERINFO, "current video mode index (used only for storage)" );
static CVAR_DEFINE_AUTO( vid_rotate, "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen rotation (0-3)" );
static CVAR_DEFINE_AUTO( vid_scale, "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "pixel scale" );
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", "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" );
CVAR_DEFINE( window_ypos, "_window_ypos", "-1", FCVAR_RENDERINFO, "window position by vertical" );
#define WINDOW_NAME XASH_ENGINE_NAME " Window" // Half-Life
convar_t *vid_fullscreen;
convar_t *vid_mode;
convar_t *vid_brightness;
convar_t *vid_gamma;
convar_t *vid_highdpi;
glwstate_t glw_state;
convar_t *window_xpos;
convar_t *window_ypos;
convar_t *vid_rotate;
convar_t *vid_scale;
/*
=================
VID_StartupGamma
=================
*/
void VID_StartupGamma( void )
{
BuildGammaTable( vid_gamma->value, vid_brightness->value );
Con_Reportf( "VID_StartupGamma: gamma %g brightness %g\n", vid_gamma->value, vid_brightness->value );
ClearBits( vid_brightness->flags, FCVAR_CHANGED );
ClearBits( vid_gamma->flags, FCVAR_CHANGED );
}
/*
=================
VID_InitDefaultResolution
@@ -52,7 +66,7 @@ void VID_InitDefaultResolution( void )
R_SaveVideoMode
=================
*/
void R_SaveVideoMode( int w, int h, int render_w, int render_h, qboolean maximized )
void R_SaveVideoMode( int w, int h, int render_w, int render_h )
{
if( !w || !h || !render_w || !render_h )
{
@@ -65,7 +79,6 @@ void R_SaveVideoMode( int w, int h, int render_w, int render_h, qboolean maximiz
Cvar_SetValue( "width", w );
Cvar_SetValue( "height", h );
Cvar_DirectSet( &vid_maximized, maximized ? "1" : "0" );
// immediately drop changed state or we may trigger
// video subsystem to reapply settings
@@ -111,11 +124,11 @@ check vid modes and fullscreen
*/
void VID_CheckChanges( void )
{
if( FBitSet( cl_allow_levelshots.flags, FCVAR_CHANGED ))
if( FBitSet( cl_allow_levelshots->flags, FCVAR_CHANGED ))
{
//GL_FreeTexture( cls.loadingBar );
SCR_RegisterTextures(); // reload 'lambda' image
ClearBits( cl_allow_levelshots.flags, FCVAR_CHANGED );
ClearBits( cl_allow_levelshots->flags, FCVAR_CHANGED );
}
if( host.renderinfo_changed )
@@ -132,36 +145,6 @@ void VID_CheckChanges( void )
}
}
/*
===============
VID_SetDisplayTransform
notify ref dll about screen transformations
===============
*/
void VID_SetDisplayTransform( int *render_w, int *render_h )
{
uint rotate = vid_rotate.value;
if( ref.dllFuncs.R_SetDisplayTransform( rotate, 0, 0, vid_scale.value, vid_scale.value ))
{
if( rotate & 1 )
{
int swap = *render_w;
*render_w = *render_h;
*render_h = swap;
}
*render_h /= vid_scale.value;
*render_w /= vid_scale.value;
}
else
{
Con_Printf( S_WARN "failed to setup screen transform\n" );
}
}
static void VID_Mode_f( void )
{
int w, h;
@@ -175,7 +158,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;
}
@@ -194,28 +177,29 @@ static void VID_Mode_f( void )
return;
}
R_ChangeDisplaySettings( w, h, bound( 0, vid_fullscreen.value, WINDOW_MODE_COUNT - 1 ));
R_ChangeDisplaySettings( w, h, Cvar_VariableInteger( "fullscreen" ) );
}
void VID_Init( void )
{
// system screen width and height (don't suppose for change from console at all)
Cvar_RegisterVariable( &window_width );
Cvar_RegisterVariable( &window_height );
Cvar_Get( "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
Cvar_Get( "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
Cvar_RegisterVariable( &vid_mode );
Cvar_RegisterVariable( &vid_highdpi );
Cvar_RegisterVariable( &vid_rotate );
Cvar_RegisterVariable( &vid_scale );
Cvar_RegisterVariable( &vid_fullscreen );
Cvar_RegisterVariable( &vid_maximized );
Cvar_RegisterVariable( &window_xpos );
Cvar_RegisterVariable( &window_ypos );
window_xpos = Cvar_Get( "_window_xpos", "-1", FCVAR_RENDERINFO, "window position by horizontal" );
window_ypos = Cvar_Get( "_window_ypos", "-1", FCVAR_RENDERINFO, "window position by vertical" );
vid_gamma = Cvar_Get( "gamma", "2.5", FCVAR_ARCHIVE, "gamma amount" );
vid_brightness = Cvar_Get( "brightness", "0.0", FCVAR_ARCHIVE, "brightness factor" );
vid_fullscreen = Cvar_Get( "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable fullscreen mode" );
vid_mode = Cvar_Get( "vid_mode", "0", FCVAR_RENDERINFO, "current video mode index (used just for storage)" );
vid_highdpi = Cvar_Get( "vid_highdpi", "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" );
vid_rotate = Cvar_Get( "vid_rotate", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen rotation (0-3)" );
vid_scale = Cvar_Get( "vid_scale", "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "pixel scale" );
// a1ba: planned to be named vid_mode for compability
// but supported mode list is filled by backends, so numbers are not portable any more
Cmd_AddRestrictedCommand( "vid_setmode", VID_Mode_f, "display video mode" );
V_Init(); // init gamma
R_Init(); // init renderer
}

View File

@@ -9,13 +9,6 @@ typedef struct vidmode_s
int height;
} vidmode_t;
typedef enum window_mode_e
{
WINDOW_MODE_WINDOWED = 0,
WINDOW_MODE_FULLSCREEN,
WINDOW_MODE_BORDERLESS,
WINDOW_MODE_COUNT,
} window_mode_t;
typedef struct
{
@@ -28,6 +21,8 @@ typedef struct
qboolean initialized; // OpenGL subsystem started
qboolean extended; // extended context allows to GL_Debug
qboolean software;
} glwstate_t;
extern glwstate_t glw_state;
@@ -35,18 +30,15 @@ extern glwstate_t glw_state;
#define VID_MIN_HEIGHT 200
#define VID_MIN_WIDTH 320
extern convar_t vid_fullscreen;
extern convar_t vid_maximized;
extern convar_t vid_highdpi;
extern convar_t window_width;
extern convar_t window_height;
extern convar_t window_xpos;
extern convar_t window_ypos;
extern convar_t gl_msaa_samples;
extern convar_t *vid_fullscreen;
extern convar_t *vid_highdpi;
extern convar_t *vid_rotate;
extern convar_t *vid_scale;
void R_SaveVideoMode( int w, int h, int render_w, int render_h, qboolean maximized );
void VID_SetDisplayTransform( int *render_w, int *render_h );
extern convar_t *gl_msaa_samples;
void R_SaveVideoMode( int w, int h, int render_w, int render_h );
void VID_CheckChanges( void );
const char *VID_GetModeString( int vid_mode );
void VID_StartupGamma( void );
#endif // VID_COMMON

View File

@@ -25,12 +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 );
static void Voice_ApplyGainAdjust( int16_t *samples, int count );
/*
===============================================================================
@@ -40,25 +39,6 @@ static void Voice_ApplyGainAdjust( int16_t *samples, int count, float scale );
===============================================================================
*/
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
@@ -67,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;
@@ -91,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 )
@@ -130,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;
}
}
@@ -153,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 );
@@ -203,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
@@ -257,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( ;; )
{
@@ -279,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 )
@@ -288,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;
}
@@ -399,7 +382,7 @@ void Voice_RecordStart( void )
{
Sound_Process( &voice.input_file, voice.samplerate, voice.width, SOUND_RESAMPLE );
voice.input_file_pos = 0;
voice.start_time = Sys_DoubleTime();
voice.is_recording = true;
}
@@ -445,9 +428,6 @@ void Voice_Disconnect( void )
voice.players_status[i].talking_ack = false;
}
}
VoiceCapture_Shutdown();
voice.device_opened = false;
}
/*
@@ -460,7 +440,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 );
}
/*
@@ -472,11 +452,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
@@ -496,7 +475,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;
@@ -521,7 +500,7 @@ 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 )
{
@@ -529,7 +508,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 );
}
}
@@ -545,7 +524,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 );
@@ -563,9 +541,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 )
@@ -611,62 +588,46 @@ Voice_Init
Initialize the voice subsystem
=========================
*/
qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
qboolean Voice_Init( const char *pszCodecName, int quality )
{
if( !voice_enable.value )
return false;
// reinitialize only if codec parameters are different
if( Q_strcmp( pszCodecName, voice.codec ) || voice.quality != quality )
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
{
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
return false;
}
// reinitialize only if codec parameters are different
if( Q_strcmp( voice.codec, pszCodecName ) && 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;
voice.autogain.block_size = 128;
if( !Voice_InitCustomMode( ))
{
// no reason to init encoder and open audio device
// if we can't hear other players
Voice_Shutdown();
return false;
}
// we can hear others players, so it's fine to fail now
voice.initialized = true;
Q_strncpy( voice.codec, pszCodecName, sizeof( voice.codec ));
if( !Voice_InitOpusEncoder( quality ))
{
Con_Printf( S_WARN "Other players will not be able to hear you.\n" );
return false;
}
voice.quality = quality;
}
if( !preinit )
if( !Voice_InitOpusDecoder( ))
{
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 )
Con_Printf( S_WARN "No microphone is available.\n" );
// 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;
}
// we can hear others players, so it's fine to fail now
voice.initialized = true;
Q_strncpy( voice.codec, pszCodecName, sizeof( voice.codec ));
if( !Voice_InitOpusEncoder( quality ))
{
Con_Printf( S_WARN "Other players will not be able to hear you.\n" );
return false;
}
voice.quality = quality;
if( !VoiceCapture_Init( ))
Con_Printf( S_WARN "No microphone is available.\n" );
return true;
}

View File

@@ -31,7 +31,7 @@ typedef struct OpusCustomMode OpusCustomMode;
#define VOICE_PCM_CHANNELS 1 // always mono
// never change these parameters when using opuscustom
#define VOICE_OPUS_CUSTOM_SAMPLERATE 44100
#define VOICE_OPUS_CUSTOM_SAMPLERATE SOUND_44k
// must follow opus custom requirements
// also be divisible with MAX_RAW_SAMPLES
#define VOICE_OPUS_CUSTOM_FRAME_SIZE 1024
@@ -53,7 +53,6 @@ typedef struct voice_state_s
qboolean initialized;
qboolean is_recording;
qboolean device_opened;
double start_time;
voice_status_t local;
@@ -62,7 +61,7 @@ typedef struct voice_state_s
// opus stuff
OpusCustomMode *custom_mode;
OpusCustomEncoder *encoder;
OpusCustomDecoder *decoders[MAX_CLIENTS];
OpusCustomDecoder *decoder;
// audio info
uint width;
@@ -71,7 +70,7 @@ typedef struct voice_state_s
// buffers
byte input_buffer[MAX_RAW_SAMPLES];
byte compress_buffer[MAX_RAW_SAMPLES];
byte output_buffer[MAX_RAW_SAMPLES];
byte decompress_buffer[MAX_RAW_SAMPLES];
fs_offset_t input_buffer_pos; // in bytes
@@ -93,7 +92,7 @@ extern voice_state_t voice;
void CL_AddVoiceToDatagram( void );
void Voice_RegisterCvars( void );
qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit );
qboolean Voice_Init( const char *pszCodecName, int quality );
void Voice_Idle( double frametime );
qboolean Voice_IsRecording( void );
void Voice_RecordStop( void );

View File

@@ -16,20 +16,22 @@ GNU General Public License for more details.
#ifndef VOX_H
#define VOX_H
#define CVOXWORDMAX 64
#define SENTENCE_INDEX -99999 // unique sentence index
#define CVOXWORDMAX 64
#define CVOXFILESENTENCEMAX 4096
#define SENTENCE_INDEX -99999 // unique sentence index
typedef struct voxword_s
{
int volume; // increase percent, ie: 125 = 125% increase
int pitch; // pitch shift up percent
int start; // offset start of wave percent
int end; // offset end of wave percent
int cbtrim; // end of wave after being trimmed to 'end'
int fKeepCached; // 1 if this word was already in cache before sentence referenced it
int samplefrac; // if pitch shifting, this is position into wav * 256
int timecompress; // % of wave to skip during playback (causes no pitch shift)
sfx_t *sfx; // name and cache pointer
int volume; // increase percent, ie: 125 = 125% increase
int pitch; // pitch shift up percent
int start; // offset start of wave percent
int end; // offset end of wave percent
int cbtrim; // end of wave after being trimmed to 'end'
int fKeepCached; // 1 if this word was already in cache before sentence referenced it
int samplefrac; // if pitch shifting, this is position into wav * 256
int timecompress; // % of wave to skip during playback (causes no pitch shift)
sfx_t *sfx; // name and cache pointer
} voxword_t;
struct channel_s;

View File

@@ -19,15 +19,13 @@ GNU General Public License for more details.
#define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
typedef struct base_command_hashmap_s base_command_hashmap_t;
struct base_command_hashmap_s
typedef struct base_command_hashmap_s
{
base_command_t *basecmd; // base command: cvar, alias or command
base_command_hashmap_t *next;
base_command_type_e type; // type for faster searching
char name[1]; // key for searching
};
base_command_t *basecmd; // base command: cvar, alias or command
const char *name; // key for searching
base_command_type_e type; // type for faster searching
struct base_command_hashmap_s *next;
} base_command_hashmap_t;
static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
@@ -126,12 +124,11 @@ void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const ch
{
base_command_hashmap_t *elem, *cur, *find;
uint hash = BaseCmd_HashKey( name );
size_t len = Q_strlen( name );
elem = Z_Malloc( sizeof( base_command_hashmap_t ) + len );
elem = Z_Malloc( sizeof( base_command_hashmap_t ) );
elem->basecmd = basecmd;
elem->type = type;
Q_strncpy( elem->name, name, len + 1 );
elem->name = name;
// link the variable in alphanumerical order
for( cur = NULL, find = hashed_cmds[hash];
@@ -162,7 +159,7 @@ void BaseCmd_Remove( base_command_type_e type, const char *name )
if( !i )
{
Con_Reportf( S_ERROR "%s: Couldn't find %s in buckets\n", __func__, name );
Con_Reportf( S_ERROR "Couldn't find %s in buckets\n", name );
return;
}

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