Begin converting QS engine to CPP
This commit is contained in:
@@ -0,0 +1 @@
|
||||
cmake-build-debug/**
|
||||
Generated
Generated
+1
@@ -0,0 +1 @@
|
||||
quakespasm
|
||||
Generated
+101
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="BackendCodeEditorSettings">
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
|
||||
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
|
||||
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakePythonSetting">
|
||||
<option name="pythonIntegrationState" value="YES" />
|
||||
</component>
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/quakespasm-0.96.3.iml" filepath="$PROJECT_DIR$/.idea/quakespasm-0.96.3.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+2
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CIDR" type="CPP_MODULE" version="4" />
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+142
@@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="CMakePresetLoader"><![CDATA[{
|
||||
"useNewFormat": true
|
||||
}]]></component>
|
||||
<component name="CMakeProjectFlavorService">
|
||||
<option name="flavorId" value="CMakePlainProjectFlavor" />
|
||||
</component>
|
||||
<component name="CMakeReloadState">
|
||||
<option name="reloaded" value="true" />
|
||||
</component>
|
||||
<component name="CMakeRunConfigurationManager">
|
||||
<generated>
|
||||
<config projectName="quakespasm" targetName="quakespasm" />
|
||||
</generated>
|
||||
</component>
|
||||
<component name="CMakeSettings">
|
||||
<configurations>
|
||||
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" />
|
||||
</configurations>
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="f5455ea3-1ba8-4b1e-84ce-0eab50a09cdc" name="Changes" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="ClangdSettings">
|
||||
<option name="formatViaClangd" value="false" />
|
||||
</component>
|
||||
<component name="ExecutionTargetManager" SELECTED_TARGET="CMakeBuildProfile:Debug" />
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="MacroExpansionManager">
|
||||
<option name="directoryName" value="5yRIaLtN" />
|
||||
</component>
|
||||
<component name="ProjectApplicationVersion">
|
||||
<option name="ide" value="CLion" />
|
||||
<option name="majorVersion" value="2026" />
|
||||
<option name="minorVersion" value="2.1" />
|
||||
<option name="productBranch" value="Classic" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo"><![CDATA[{
|
||||
"associatedIndex": 6,
|
||||
"fromUser": false
|
||||
}]]></component>
|
||||
<component name="ProjectId" id="3IFldDeo8ZZSrZixdcT6JdBiaj1" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"CMake Application.quakespasm.executor": "Run",
|
||||
"CidrDebugProfileConversion": "true",
|
||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||
"RunOnceActivity.RadMigrateCodeStyle": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"RunOnceActivity.cidr.known.project.marker": "true",
|
||||
"RunOnceActivity.readMode.enableVisualFormatting": "true",
|
||||
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
||||
"cf.first.check.clang-format": "false",
|
||||
"cidr.known.project.marker": "true",
|
||||
"codeWithMe.voiceChat.enabledByDefault": "false",
|
||||
"git-widget-placeholder": "master",
|
||||
"last_opened_file_path": "/home/iikorni/Downloads/quakespasm-0.96.3",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.jshint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.jshint": "",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RecentsManager">
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/cmake-build-debug" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration default="true" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration name="quakespasm" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="quakespasm" TARGET_NAME="quakespasm" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="quakespasm" RUN_TARGET_NAME="quakespasm">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="SelectedDebugProfileService"><![CDATA[{
|
||||
"profileIdByStamp": [
|
||||
{
|
||||
"first": {
|
||||
"##RUN_CONFIGURATION##": "CMake Application.quakespasm",
|
||||
"cmake": "CMakeBuildProfile:Debug"
|
||||
},
|
||||
"second": "27852a6b-aee6-4e6c-a703-78c08d632bb7"
|
||||
}
|
||||
],
|
||||
"modificationCount": 4
|
||||
}]]></component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="f5455ea3-1ba8-4b1e-84ce-0eab50a09cdc" name="Changes" comment="" />
|
||||
<created>1787368285525</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1787368285525</updated>
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="VCPKGProject">
|
||||
<isAutomaticCheckingOnLaunch value="false" />
|
||||
<isAutomaticFoundErrors value="true" />
|
||||
<isAutomaticReloadCMake value="true" />
|
||||
<isAutomaticBootstrapAfterUpdate value="false" />
|
||||
</component>
|
||||
<component name="Vcs.Log.Tabs.Properties">
|
||||
<option name="TAB_STATES">
|
||||
<map>
|
||||
<entry key="MAIN">
|
||||
<value>
|
||||
<State />
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
cmake_minimum_required(VERSION 4.3)
|
||||
project(quakespasm)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 26)
|
||||
|
||||
find_package(SDL)
|
||||
find_package(SDL_net)
|
||||
find_package(OpenGL)
|
||||
|
||||
add_executable(quakespasm Quake/bgmusic.cpp Quake/cd_sdl.cpp Quake/cfgfile.cpp Quake/chase.cpp Quake/cl_demo.cpp Quake/cl_input.cpp Quake/cl_main.cpp Quake/cl_parse.cpp Quake/cl_tent.cpp Quake/cmd.cpp Quake/common.cpp Quake/console.cpp Quake/crc.cpp Quake/cvar.cpp Quake/gl_draw.cpp Quake/gl_fog.cpp Quake/gl_mesh.cpp Quake/gl_model.cpp Quake/gl_refrag.cpp Quake/gl_rlight.cpp Quake/gl_rmain.cpp Quake/gl_rmisc.cpp Quake/gl_screen.cpp Quake/gl_sky.cpp Quake/gl_texmgr.cpp Quake/gl_vidsdl.cpp Quake/gl_warp.cpp Quake/host.cpp Quake/host_cmd.cpp Quake/image.cpp Quake/in_sdl.cpp Quake/keys.cpp Quake/main_sdl.cpp Quake/mathlib.cpp Quake/menu.cpp Quake/miniz.cpp Quake/net_bsd.cpp Quake/net_dgrm.cpp Quake/net_loop.cpp Quake/net_main.cpp Quake/net_udp.cpp Quake/pl_linux.cpp Quake/pr_cmds.cpp Quake/pr_edict.cpp Quake/pr_exec.cpp Quake/r_alias.cpp Quake/r_brush.cpp Quake/r_part.cpp Quake/r_sprite.cpp Quake/r_world.cpp Quake/sbar.cpp Quake/snd_codec.cpp Quake/snd_dma.cpp Quake/snd_flac.cpp Quake/snd_mem.cpp Quake/snd_mikmod.cpp Quake/snd_mix.cpp Quake/snd_modplug.cpp Quake/snd_mp3.cpp Quake/snd_mp3tag.cpp Quake/snd_mpg123.cpp Quake/snd_opus.cpp Quake/snd_sdl.cpp Quake/snd_umx.cpp Quake/snd_vorbis.cpp Quake/snd_wave.cpp Quake/snd_xmp.cpp Quake/strlcat.cpp Quake/strlcpy.cpp Quake/sv_main.cpp Quake/sv_move.cpp Quake/sv_phys.cpp Quake/sv_user.cpp Quake/sys_sdl_unix.cpp Quake/view.cpp Quake/wad.cpp Quake/world.cpp Quake/zone.cpp )
|
||||
|
||||
target_link_libraries(quakespasm OpenGL::GL)
|
||||
target_link_libraries(quakespasm SDL::SDL)
|
||||
target_link_libraries(quakespasm vorbisfile)
|
||||
target_link_libraries(quakespasm vorbis)
|
||||
target_link_libraries(quakespasm ogg)
|
||||
target_link_libraries(quakespasm mad)
|
||||
target_link_libraries(quakespasm m)
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
@@ -0,0 +1,417 @@
|
||||
|
||||
================================================================================
|
||||
|
||||
Fitzquake version 0.80, May 26, 2005
|
||||
|
||||
Filename : fitzquake080.exe
|
||||
Author : John Fitzgibbons
|
||||
Email Address : [email protected]
|
||||
Author's Homepage : http://www.celephais.net/
|
||||
Fitzquake Homepage : http://www.celephais.net/fitzquake
|
||||
|
||||
Fitzquake is a modified glquake based on the source code released by id
|
||||
Software. My primary focus is fixing a lot of the rendering bugs which made
|
||||
glquake inferior to the software renderer. My secondary focus is adding
|
||||
conveniences for mappers and general users. I am also slowly adding support for
|
||||
new modding or mapping features such as skyboxes, fog, and colored light.
|
||||
|
||||
While I have made extensive changes to the code, I pretty much use the same
|
||||
OpenGL features that the original glquake uses. Therefore, if you can run
|
||||
glquake, you can probably run Fitzquake.
|
||||
|
||||
I am not finished working on this project, so bug reports and feature requests
|
||||
are welcome.
|
||||
|
||||
Acknowlegements
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
id Software (quake and quake2 code)
|
||||
LordHavoc (code and assistance)
|
||||
Bengt Jardrup (feedback, assistance, testing)
|
||||
|
||||
additional thanks to: Aardappel, SmallPileOfGibs, FrikaC, Vondur, Topaz, Tomaz,
|
||||
Tonik, Radix, EvilTypeGuy, NightBringer, MH, Maddes, Fett, Craig Wills, Heffo,
|
||||
Riot, Gleeb, people in #flipcode, and others for their tutorials, code, testing,
|
||||
and assistance.
|
||||
|
||||
Copyright / Permissions
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2005 John Fitzgibbons and others
|
||||
|
||||
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.
|
||||
|
||||
History
|
||||
================================================================================
|
||||
|
||||
changes in 0.80
|
||||
---------------
|
||||
|
||||
- map loading is about four times faster. This is due to some optimizations in the texture loading code.
|
||||
- video mode can now be changed in-game. You can change resolution, color depth, refresh rate, and switch between windowed and fullscreen modes. This can be accomplished easily using the video options menu, and is also available at the console using cvars. Note: if you launch fitzquake with -width, -height, -window, or -bpp in the command line, Fitzquake will use the command line settings and ignore whatever it reads from the config files at startup. However, you will still be able to change the video mode from the menu or the console as you like. Also note: to change video modes by execing a config file, the config file must include "vid_restart" after the other vid_ cvars have been set. (see cvars "vid_width," "vid_height," "vid_fullscreen," "vid_bpp," "vid_refreshrate," and commands "vid_restart," "vid_test")
|
||||
- added control of entity count limits (MAX_EDICTS.) The default maximum has been increased from 600 to 1024. It can be raised even higher (up to 8192 -- this is a limit set by the network protocol) using a cvar. (see cvar "max_edicts")
|
||||
- added control of vertical sync. (see cvar "vid_vsync")
|
||||
- added control of anistropic filtering. Anisotropic filtering is a method to improve texture clarity on surfaces when viewed at steep angles. (see cvar "gl_texture_anisotropy")
|
||||
- console buffer size can now be set. The command line option "-consize" allows you to specify the buffer size in kilobytes. For reference, fitzquake's default buffer size is 64k, and glquake's is 16k. 16k is also the smallest size fitzquake will allow you to set. Note: this buffer lives in the heap, so if you want to have a HUGE buffer, you might need to increase -heapsize also.
|
||||
- increased max surface extents from 256 (the software quake maximum) to 2000. For reference, the glquake maximum is 512. This should eliminate the "bad surface extents" crash when running some maps that could be played in glquake, but not fitzquake or winquake.
|
||||
- increased max vertices in an alias model from 1024 (the glquake maximum) to 2000 (the software quake maximum.)
|
||||
- increased MAX_CHANNELS from 128 to 512 and MAX_DYNAMIC_CHANNELS from 8 to 128
|
||||
- screenshot filenames are now in the format "fitz0000.tga", increasing the maximum number of screenshots per folder from one hundred to ten thousand.
|
||||
- vid_describemodes output cleaned up; now displays a list of valid refresh rates for each mode
|
||||
- added a more intuitive cvar control of slow motion/fast-forward for demos and live gameplay. (see cvar "host_timescale")
|
||||
- "reset to defaults" option in the menu now executes the "resetall" command before loading default.cfg
|
||||
- game command now writes config.cfg to current gamedir before switching
|
||||
- +mlook is now saved to config.cfg
|
||||
- changed smallest allowed window size from 320x240 to 320x200
|
||||
- console cursor images are now hard-coded, and the insert mode cursor is now a vertical bar instead of an underscore. This was prompted by several popular mods (OUM, Xmen TC) using nonstandard cursors, which are incompatible the fitzquake console enhancements.
|
||||
- gl_farclip now defaults to 16384. This should be high enough to handle even the largest open areas without unwanted clipping. The only reason you'd want to lower this number is if you see z-fighting.
|
||||
- added cvar r_drawworld (see below)
|
||||
- added cvar r_showtris (see below)
|
||||
- added cvar r_showbboxes (see below)
|
||||
- added a command to cycle a cvar through a list of values. (see command "cycle")
|
||||
- mapname command now works on dedicated server.
|
||||
- added a hack to fix those white edges on the bottom of the large box of shells. I feel dirty, but they look better, now.
|
||||
- changed stuffcmds behavior to allow hyphenated map names, config file names, etc. in the command line. (example: "fitzquake.exe +exec my-config.cfg +map my-map") However, you still can't load a map or config file when the first character in the filename is a hyphen.
|
||||
- skybox loader now reverts to scrolling sky if all 6 skybox faces failed to load.
|
||||
- tweaked circular particles to match the apparent size of the square particles.
|
||||
- fixed crash when loading mods with large player skins (like the chainsaw mod, and PerQuake.) Colormapping can now handle any size player texture (limited to the heapsize, of course.)
|
||||
- fixed bug where a replacement model in a mod is messed up becuase a matching .ms2 file in id1/glquake is present. The fix is simply to disable all mesh caching, which slows down model loading a little.
|
||||
- fixed freeze when gl_overbright is 1 and either texture_env_combine or multitexture is disabled or not supported.
|
||||
- fixed "numgltextures == MAX_GLTEXTURES" crash when viewing multiplayer->setup menu.
|
||||
- fixed "numgltextures == MAX_GLTEXTURES" crash when playing large maps (nesp09,) due to frequent model recaches.
|
||||
- fixed bug where entities and water were not being drawn any frame in which a model had to be recached.
|
||||
- fixed skybox texture showing up in the place of other textures/skins/lightmaps, when the previous loaded map had a skybox.
|
||||
- fixed missing polygons on edges of screen when underwater and r_waterwarp is 1.
|
||||
- fixed missing polygons on edges of screen when r_stereo is enabled.
|
||||
- fixed long mapnames that scroll are truncated to be shorter than what appears in the console. Well, sort of. What I did was increase the maximum length from 39 to 127. A mapname longer than 127 will still be truncated, but these are pretty rare.
|
||||
- fixed rogue's teamplay skin showing up as an all-white texture.
|
||||
- fixed checkerboard texture shows up sometimes when an animated texture has fullbright pixels on some frames, but not others (reactor core in junk.bsp)
|
||||
- fixed color 255 is not fullbright
|
||||
- fixed fuscia dots appearing in corners of resampled textures
|
||||
- fixed mapname command crashes when client is disconnected.
|
||||
- fixed cl_nolerp 1 screws up speed of demo playback
|
||||
- fixed annoying client-side step-up smoothing when in noclip mode (except on nonlocal servers.)
|
||||
- fixed scr_clock 2 displays hour twelve as "0" instead of "12"
|
||||
- fixed skip textured surfaces still drawn even after running tyrann's skip utility
|
||||
- fixed crash when loading a map with a sky texture where the "sky" in the texturename is not lowercase
|
||||
- fixed hang in e2m2 on easy skill, where you can shoot one of the buttons at the beginning and then trick-jump through the open gate. Now it prints a warning message ("SV_TouchLinks: null link") and lets you keep playing.
|
||||
- fixed bug when viewsize < 100, and r_oldwater is 0, where you can see the water textures overlaying part of the brown frame around the viewport.
|
||||
- fixed bug where imagelist and r_speeds2 would report the same megabyte counts in both 16bpp and 32bpp mode, even though texture bpp should match (and does match) framebuffer bpp. The numbers are now different and accurate for each bit depth.
|
||||
- removed cvars "vid_config_x," "vid_config_y," "vid_wait," "vid_nopageflip," "_vid_wait_override," "_vid_default_mode," "_vid_default_mode_win," and "vid_stretch_by_2," none of which glquake ever used.
|
||||
- removed cvar "vid_mode" and commands "vid_describemode" and "vid_nummodes," because of the new video mode handling.
|
||||
|
||||
cvars:
|
||||
|
||||
- gl_texture_anisotropy. Controls the amount of anisotropy in texture filtering. If 1 or less than 1, texture filtering is normal (isotropic.) If greater than 1, increasing degrees of anisotropic filtering are used, up to the hardware maximum. Set value to 2 for 2x anisotropic, 4 for 4x, etc. Default 1.
|
||||
|
||||
- host_timescale. Scales the passage of time on client and server. Set to 0 or 1 for normal speed, less than 1 for slow motion, and greater than 1 for fast-forward. If greater than 0, overrides host_framerate. Default 0.
|
||||
|
||||
- max_edicts. Sets the maximum number of entites on both the client and server. Default 1024. Acceptable values range from 256 to 8192. Set to 600 to mimic standard quake. Changes won't take effect until the next time a map is loaded. Note: if a client connects to a server, and the client's maximum is lower than the server's, the client will probably crash if it ever sees an entnum higher than its local max_edicts. Warning: you may need to increase -heapsize if you want a high max_edicts value.
|
||||
|
||||
- r_drawworld. If 1, draw world as usual. If 0, don't draw the world. Default 1. (compare r_drawentities)
|
||||
|
||||
- r_showbboxes. If 1, draw a wireframe bounding box around each entity. Note that these are the server-side per-edict physics bounding boxes, not the client-side per-model rendering bboxes. If 0, disable this feature. Default 0.
|
||||
|
||||
- r_showtris. If 1, draw wireframe outlines for every triangle in the scene. Like in Quake 3, the lines will be visible even through solid geometry. If 2, draw the outlines only on visible surfaces (like r_showtris 2 in Medal of Honor.) If 0, disable wireframe overlay. Default 0.
|
||||
|
||||
- vid_bpp. Sets the color depth of the screen in fullscreen mode. Windowed mode ignores this setting. Can be 16 or 32. Default 16. (Changes won't take effect until the next call to vid_restart.)
|
||||
|
||||
- vid_fullscreen. If 1, fitzquake will run fullscreen. If 0, fitzquake will run in a window. Default 1. (Changes won't take effect until the next call to vid_restart.)
|
||||
|
||||
- vid_height. Sets the vertical screen/window resolution. Default 480. In windowed mode, cannot be less than 200. (Changes won't take effect until the next call to vid_restart.)
|
||||
|
||||
- vid_refreshrate. Sets the refresh rate of the screen in fullscreen mode. Windowed mode ignores this setting. Possible values include 60, 70, 72, 75, 85, etc. Default 60. (Changes won't take effect until the next call to vid_restart.)
|
||||
|
||||
- vid_width. Sets the horizontal screen/window resolution. Default 640. In windowed mode, cannot be less than 320. (Changes won't take effect until the next call to vid_restart.)
|
||||
|
||||
- vid_vsync. Set to 1 to enable vertical sync, which eliminates tearing, but caps your framerate at the monitor refreshrate. Set to 0 to disable vertical sync, which allows tearing but doesn't cap your framerate. Default 0. Note: If fitzquake detects that your driver settings have forced vsync to be disabled, it will post a message to the console saying so, and this cvar will have no effect.
|
||||
|
||||
commands:
|
||||
|
||||
- "cycle <cvar> <value> [<value> [<value> ...]]" to cycle a cvar through a list of values.. Note: this command will get stuck on a list that contains the same value more than once, such as "cycle blah 1 2 1 3". If you're doing anything that complex you can just use aliases.
|
||||
|
||||
- vid_restart. Tries to set a video mode that matches the values of vid_width, vid_height, vid_fullscreen, and, if vid_fullscreen is 1, vid_bpp and vid_refreshrate.
|
||||
|
||||
- vid_test. Like vid_restart, except that after switching to the new mode pops up a confirmation dialogue. This is useful if you are not sure what modes your monitor can handle, so you don't get stuck with a blank screen. The dialogue has a time limit so that if you don't press a key within 5 seconds, it will revert to the previous mode.
|
||||
|
||||
changes in 0.75
|
||||
---------------
|
||||
|
||||
- totally rewritten bsp drawing code. The new code combines the advantages of the gl_texsort 1 and gl_texsort 0 codepaths from glquake into one codepath that uses texture sorting and multitexture. In my tests, i've found that it's about the same speed as glquake in low poly scenes (like the original quake levels,) but as you get into the thousands of wpolys, it's faster and faster.
|
||||
- 2x overbright lighting. Lighting now looks like software quake. Just like overbright lighting on models, overbright on world polys requires GL_EXT_texture_env_combine (TNT and later, voodoo4 and later.) Without it, FitzQuake will be use two passes to render overbright world polys. So if you don't have that extension, you might disable it for performance reasons. (see cvar "gl_overbright")
|
||||
- colored lighting support using .lit files.
|
||||
- totally new water surface animation. The new method requires no surface subdivision, isn't plagued by tearing and sparklies caused by tjunctions, and looks almost identical to software quake's water, and doesn't slow down on very large sheets of water. (see cvars "r_waterquality" and "r_oldwater")
|
||||
- old water aninmation fixed so that it doesn't look bad when gl_subdivide_size is 32 or lower.
|
||||
- can load external textures (currently targa and pcx) if they match the texture name in the bsp and are located in the id1/textures, or <MODDIR>/textures directory. At the moment no other images (skins, menu, etc.) can be replaced.
|
||||
- gamma correction now goes back to normal when Fitzquake loses focus.
|
||||
- tab completion now adds a space after the completed command/cvar if the cursor is at the end of the editline.
|
||||
- increased the max length of the video mode list from 30 to 80. This should alleviate the problems people with newer cards were having trying to use some 32-bit modes -- there were so many 16-bit modes that they filled up the list before all 32-bit modes could be detected. The video menu will still only list a certain number of modes due to space constraints, but you can see the complete list by using the console command "vid_describemodes"
|
||||
- number of listed video modes in the "video options" menu increased from 27 to 36.
|
||||
- added alpha control for the front sky layer. (see cvar "r_skyalpha")
|
||||
- clock can now display time in 24-hour or "military" time.
|
||||
- added an "mtex" counter to the r_speeds 2 readout. This measures the number of megabytes of texture memory used each frame to draw the scene. Note: this doesn't count textures used to draw the console, menu, or statusbar.
|
||||
- added optional drawing of surfaces inside sky leaves, for compiler/map testing purposes. (see cvar "r_oldskyleaf")
|
||||
- sky surfaces on bmodels are now visible, though drawn incorrectly.
|
||||
- fixed multiple textures in bsp with same name or no name get overwritten/not loaded. (example: rd1m3)
|
||||
- fixed some nasty texture loading bugs that were especially hounding 3dfx users (wrong texture, no texture, or unnecessarily low-res textures displayed on models and world.) These bugs would also occur in conjunction with nonzero values of gl_max_size or gl_picmip.
|
||||
- fixed bug where changing gl_max_size or gl_picmip in-game would screw up alias model texture coordinates.
|
||||
- fixed bug where if -gamma is specified at the command line, the "gamma" cvar would be ignored.
|
||||
- fixed model more than 2048 units above floor us unlit by static lighting.
|
||||
- fixed crash with con_logcenterprint when centerprint message was too long.
|
||||
- fixed crash when changing to a nonexistant gamedir and then trying to write a file (screenshot, etc.) Fitzquake now creates the directory as needed.
|
||||
- fixed "bad surface extents" error when sky or water surface is missing from bsp file.
|
||||
- fixed alias model shadows write to z-buffer.
|
||||
- fixed underwater intermission camera has warp, but no screenblend.
|
||||
- fixed console buffer still scrolled back after using the "clear" command.
|
||||
- fixed console command history (the list of previous commands) not being rewound after toggling the console.
|
||||
- removed cvar gl_texsort. New bsp drawing code always sorts by texture.
|
||||
- removed cvar gl_ztrick. The depth buffer is now cleared every frame.
|
||||
- removed cvar gl_keeptjunctions. Extra verts created by qbsp to eliminate tjunctions are now always kept.
|
||||
- removed "sliding on monsters' heads" fix, becuase I decided I don't like the idea of changing gameplay, even if the original behaviour is clearly a bug. Since this bug can be fixed in quakec also, I feel safer leaving it as it was.
|
||||
|
||||
cvars:
|
||||
|
||||
- gl_overbright. default 1. This variable controls overbright lighting on the world polygons. (For lighting on models, use gl_overbright_models.) If 1, overbright will be enabled and lighting will resemble software Quake. If 0, overbright will be disabled and lighting will resemble GLQuake.
|
||||
|
||||
- r_oldskyleaf. default 0. If 0, surfaces inside sky leaves will be skipped by the renderer. If 1, they will be drawn whenever they are in your PVS, just like any other surface.
|
||||
|
||||
- r_oldwater. default 1. If 1, use the old GLQuake method of subdividing the water surface to enable a warping animation. If 0, use the new render-to-texture method. Note: in general, r_oldwater 0 looks better and runs slower. So experiment to see if the performance hit is acceptable to you.
|
||||
|
||||
- r_skyalpha. default 1. Sets the alpha of the front sky layer. Note that if sky alpha is less than 1.0, the sky will be drawn in two passes even if you have multitexture.
|
||||
|
||||
- r_waterquality. default 8. Sets the quality of the water when r_oldwater is 0. Can be anywhere from 1 to 64. Lower values give better performance, higher values look better. A value of 4 will provide water that looks at least as good as glquake can get, and 32 is close enough to software quake for all but the most picky. To control the quality of water when r_oldwater is 1, use gl_subdivide_size instead.
|
||||
|
||||
- scr_clock. default 0. If 1, game time is displayed. If 2, system time is displayed in 12-hour format. If 3, system time will be displayed in 24-hour or "military" time.
|
||||
|
||||
Changes in 0.70
|
||||
---------------
|
||||
|
||||
- added anaglyph stereo rendering. Note that this will cut your framerate in half, as it is rendering the scene once for each eye. You might want to turn off r_drawviewmodel as it is hard to focus on becuase it is so close. (see cvars "r_stereo", "r_stereodepth")
|
||||
- now uses ARB_multitexture if present, otherwise tries to use SGIS_multitexture. This should fix various blending bugs on some cards, such as weird cloud layers, all-black models, and inverted torches. (only ARB guarantees that GL_DECAL blending will work)
|
||||
- overbright models now uses GL_EXT_texture_env_combine if supported (TNT and later, voodoo4 and later,) which saves one or two passes on model rendering when gl_overbright_models is 1. The command line option -nocombine will disable this.
|
||||
- gl_overbright_models now defaults to 1
|
||||
- custom palettes are now correctly loaded when you use the "game" command.
|
||||
- RecursiveLightPoint is now lerped for smoother lighting of slow-moving models. Check out the ogre in e3m3 for an example.
|
||||
- dynamic lighting (rockets, etc) has been moderately sped up. (some lightmaps were being uploaded even though they weren't actually touched by a dynamic light.)
|
||||
- overhauled 2d drawing to allow independent scaling of console, menu, and sbar (see cvars "scr_conwdith," "scr_menuscale," and "scr_sbarscale") command line switches "-conwidth" and "-conheight" removed. cvar "scr_stretch_menus" removed.
|
||||
- user control of max framerate. (see cvar "host_maxfps")
|
||||
- improved the accuracy of the FPS counter a bit, but it still seems suspect.
|
||||
- particles can now be drawn as quads or triangles. (see cvar "r_quadparticles")
|
||||
- opengl information (vendor, renderer, version, extensions) is no longer printed during initialization. (see command "gl_info")
|
||||
- rewrote texture management. Now instead of quake's memory usage going up and up forever (becuase textures were uploaded to the opengl.dll and never freed,) all textures will get flushed when you switch games, bringing you back down to where you were when fitzquake first launched.
|
||||
- gl_texturemode command will now accept a number (1 through 6) as well as the name (gl_linear_mipmap_nearest, etc.)
|
||||
- gl_describetexturemodes will list all texturemodes.
|
||||
- the inside of sky leaves are no longer rendered -- so when noclipping inside them, it will look the same as noclipping inside a solid wall. This does not affect gameplay.
|
||||
- cleaned up intermission display in singleplayer -- no more overlapping numbers
|
||||
- r_speeds readout modified a bit. (see cvar "r_speeds")
|
||||
- r_sky_quality now defaults to 12 instead of 8, since skies are now drawn in 1 pass (with multitexture at least)
|
||||
- gl_texsort now always defaults to 0. (it used to be forced to 1 when multitexture was unavailable)
|
||||
- fixed bug where models would actually darken when dlights got bright enough
|
||||
- fixed deathmatch, coop cvars not reset to zero when starting a new game from the single player menu
|
||||
- fixed r_lightmap doesn't work when gl_texsort = 0.
|
||||
- fixed inverted lightmaps / no textures / no dynamic light bug when multitexture is disabled and gl_texsort = 0
|
||||
- fixed scrolling map title in wrong place when width does not equal conwidth
|
||||
- fixed a few color borking problems in 16-bit mode. The front sky layer, sprites, and pics with transparency will still look a bit off (as in glquake,) but at least the console image and statusbar background look better. Though it isn't perfect, it should once again look like what you expect from glquake in 16bit.
|
||||
- fixed pixel gap on both sides of the console in 1024x768
|
||||
- fixed wpoly count being slightly lower when gl_texsort = 0 (the count was correct when gl_texsort = 1)
|
||||
- fixed lmap count always zero when gl_texsort = 1
|
||||
- dlight fans are now drawn after water, so that it looks right at least when wateralpha is 1.
|
||||
- fixed a possible bug with older 3dfx cards (voodoo 1/2/rush) where the gamma cvar might not work (untested)
|
||||
- fixed old commands showing up in the console prompt after hitting 'enter'
|
||||
- increased MAX_HANDLES so that you should never see the "out of handles" error message.
|
||||
- removed cvar "chase_alpha." the transparent player model was buggy and didn't work well in a lot of conditions.
|
||||
- removed cvar "gl_doubleeys" (yes, that is the correct misspelling) With overbright models, eyes can be seen as easily as in software mode.
|
||||
- removed cvars "cl_crossx," "cl_crossy," "lcd_x," "lcd_yaw," and "gl_reporttjunctions" which didn't do anything (in glquake, at least).
|
||||
- removed support for GL_EXT_shared_texture_palette (special 8-bit texture format)
|
||||
- removed VCR code. command line switches "-record" and "-playback" no longer supported.
|
||||
- removed support for command line switch "-gamma" -- just use the gamma cvar, or idgamma or something.
|
||||
|
||||
cvars:
|
||||
|
||||
- r_stereo. default 0. If nonzero, the scene will be rendered once in red, and again in cyan, with the two views shifted slightly. If you have 3D glasses you can appreciate this (assumes that the left eye is red and the right eye is cyan.) The value of r_stereo sets the eye separation. If your glasses have red on the right eye, use a negative value to flip the views.
|
||||
|
||||
- r_stereodepth. default 128. Sets the distance at which the two views will converge when stereo rendering is active.
|
||||
|
||||
- scr_conwdith. default 0. Sets the virtual console width, where smaller numbers means larger text. Values larger than window width, or smaller than 320, will be clamped to that range, and all values will be rounded to a multiple of 8. If 0, the window width will be used. Note that values that divide evenly into the window width will make the text look nicest.
|
||||
|
||||
- scr_menuscale. default 1. Sets the scale factor for menus and other centered overlays. If 1, images will be drawn at 1:1 scale. If 2, images will be double size. Menus will never be drawn smaller than 1:1, and never larger than the size of the window. Note that integer values will make the text look nicest.
|
||||
|
||||
- scr_sbarscale. default 1. Sets the scale factor for the statusbar. If 1, images will be drawn at 1:1 scale. If 2, images will be double size. The statusbar will never be drawn smaller than 1:1, and never larger than the width of the window. Note that integer values will make the text look nicest.
|
||||
|
||||
- host_maxfps. default 72. sets the maximum frames per second fitzquake will render (also the maximum number of server frames per second.) Clamped to the range 10 - 1000. Set to 72 to mimic standard quake.
|
||||
|
||||
- r_quadparticles. default 1. If 1, particles are drawn as GL_QUADS instead of GL_TRIANGLES. Quads use 4 verts instead of 3, but the fillrate cost is 1/2 that of triangles. Depending on your card, either one may be faster. This cvar has no effect on the appearance of particles.
|
||||
|
||||
- r_speeds. default 0. Values of 1 and 2 will give you increasing amounts of information. When you see two numbers separated by a slash, the first number is polys, and the second number is passes.
|
||||
|
||||
commands:
|
||||
|
||||
- gl_info. Displays opengl info which was previously displayed during initialization: vendor, renderer, version, and extensions
|
||||
|
||||
- imagelist. Displays a list of loaded textures, and their dimentions.
|
||||
|
||||
- gl_texturemode. Now accepts a number (1 through 6) as well as the name (gl_nearest, etc.)
|
||||
|
||||
- gl_describetexturemodes. Lists all texturemodes.
|
||||
|
||||
Changes in 0.65
|
||||
---------------
|
||||
|
||||
- gamma cvar now supported. (see cvar "gamma")
|
||||
- fullbrights on models now supported.
|
||||
- odd-sized world textures are now bilinearly resampled (instead of glquake's nearest pixel resample)
|
||||
- removed all fixed-size buffers for loading textures; now the only limit is the size of your memory heap (textures will still be downsampled if they are bigger than the hardware can handle)
|
||||
- styled lights (torch flicker, etc.) can now be disabled (see cvar "r_flatlightstyles")
|
||||
- sky now uses multitexture if available.
|
||||
- centerprints are now optionally logged to the console (see cvar "con_logcenterprint")
|
||||
- number of savegame slots increased to 20 (from 12)
|
||||
- if a map title is longer than 22 characters, it scrolls marquee-style in the statusbar.
|
||||
- gl_flashblend defaults to 1 again. (consistency with glquake)
|
||||
- gl_ztrick defaults to 1 again. (consistency with glquake)
|
||||
- command line gamma now defaults to 1.0 for all cards. (consistency with glquake, plus hardware gamma is better)
|
||||
- now checks hardware for maximum texture size. Users of later voodoo cards should be able to see large textures now. (see cvar "gl_max_size")
|
||||
- now shows AM/PM when scr_clock is 2
|
||||
- fixed crash when starting dedicated server
|
||||
- fixed crash when loading too many textures. (now it throws a sys_error and quits)
|
||||
- fixed fitzquake-specific crash when player goes near water in a demo playback.
|
||||
- scr_conalpha now actually works.
|
||||
- keypad enter in the console works again.
|
||||
- optional 2x overbrightening on models. (see cvar "gl_overbright_models")
|
||||
- optional quake2-style noclip. (see cvar "sv_altnoclip")
|
||||
- new icon
|
||||
|
||||
cvars:
|
||||
|
||||
- con_logcenterprint: If 1, centerprint messages will be logged to the console in sp/coop. If 2, they will also be logged in deathmatch. Default 1.
|
||||
|
||||
- gamma: Brighten or darken the screen to compensate for differences between monitors. This is now supported by using your video card's gamma support. Just like in winquake, values less than 1 are brighter and values greater than one are darker. Default 1. Notes: I have added special code so that this will work on 3dfx cards too, but i have no way to check that it works. If fitzquake crashes, your hardware gamma may be stuck at the wrong value. You can use the "display settings" control panel fix this, or you could try lordhavoc's useful "setgamma" utility (available on this page.) Also note that if texture-brightening gamma has been requested at the command line (fitzquake.exe -gamma ), harware gamma will not be used and the gamma cvar will have no effect.
|
||||
|
||||
- gl_max_size: Now defaults to 0. If 0, textures will be as large as the hardware allows. Positive values can be used to impose a limit smaller than the hardware's reported maximum.
|
||||
|
||||
- gl_overbright_models: If 1, models will be rendered using 2x overbrightening and will appear at roughly the same brightness as they do in software quake, which is noticably brighter than the default fitzquake / glquake appearance. I disabled this cvar by default becuase this is still a poorly supported feature -- it currently takes 2 or 3 passes to render a model when this feature is enabled, compared to only 1 pass when it is disabled. Default 0.
|
||||
|
||||
- r_flatlightstyles: If 1, styled lights (torch flicker, etc.) will be displayed as a steady light. If 2, the peak intensity will be used instead of the average intensity. Default 0.
|
||||
|
||||
- sv_altnoclip: If 1, enable the alternative noclip movement which resembles quake2 and is not constrained to the horizontal plane. Set to 0 to retain quake's original noclip behavior. Default 1.
|
||||
|
||||
Changes in 0.60
|
||||
---------------
|
||||
|
||||
- graphics:
|
||||
- better sky projection, configurable for performance
|
||||
- menus and other overlays are now centered on the screen, and can optionally stretch to fit resolution.
|
||||
- all 2d graphics now obey gl_texturemode and all texturemode changes take effect immediately
|
||||
- underwater warping now resembles quake3's perspective munging, and obeys r_waterwarp
|
||||
- fixed frustum culling b0rked (giving HOM at certain FOV / vidsize / screensize combinations)
|
||||
- fixed lack of support for VP_PARALLEL_ORIENTED, VP_PARALLEL_UPRIGHT, and FACING_UPRIGHT sprites
|
||||
- fixed fullbrights not displayed on world/bmodels
|
||||
- fixed texture cache mismatch error
|
||||
- fixed pink edges on sprites, menu items, etc
|
||||
- fixed particle z-buffer bug (apparent when a particle is in front of a water surface)
|
||||
- fixed ugly resampling of non-power of two gfx, skins, sprites
|
||||
- fixed large models (shamblers, shub) dissapearing near edge of screen
|
||||
- fixed statusbar not visible when gl_clear = 1
|
||||
- fixed r_fullbright change not immedate when gl_texsort = 0
|
||||
- fixed alias models still dark when r_fullbright = 1
|
||||
- fixed HOM when screen is partially underwater
|
||||
- fixed gunshot decals not showing up on some walls
|
||||
- sky and water warp now freeze when you pause, as well as lightning bolts
|
||||
- r_novis changes now take effect immediately, rather than when you cross a leaf boundary
|
||||
- removed mirror code
|
||||
- two particle styles, circle and square (cvar controlled)
|
||||
- console:
|
||||
- improved tab completion:
|
||||
- hitting tab once will display a list of possible matches and complete the line using the first match
|
||||
- hitting tab or shift-tab will cycle through the matches
|
||||
- autocomplete will now match against aliases as well as commands and cvars.
|
||||
- autocomplete will now complete later in the string (e.g. "bind mouse1 +att" + tab will complete '+attack')
|
||||
- autocomplete will even complete inside the string (e.g. "bind m +attack" + tab will complete 'mouse1' if the cursor is right after the 'm')
|
||||
- new key functionality:
|
||||
- tab -- autocomplete, cycle through multiple matches
|
||||
- shift-tab -- cycle backwards through multiple matches
|
||||
- ins -- toggle insertmode
|
||||
- del -- delete current character
|
||||
- backspace -- delete previous character
|
||||
- ctrl-v -- paste from windows clippboard
|
||||
- leftarrow -- move cursor one character left in line
|
||||
- rightarrow -- move cursor one character right in line. or, get one character from the previous command.
|
||||
- home -- move cursor to beginning of line
|
||||
- end -- move cursor to end of line
|
||||
- ctrl-pgup -- scroll up a screen at a time
|
||||
- ctrl-pgdn -- scroll down a screen at a time
|
||||
- ctrl-home -- scroll to top of console history
|
||||
- ctrl-end -- scroll to bottom of console history
|
||||
- carets indicate that you are scrolled back, like in quakeworld/quake2
|
||||
- left arrow, right arrow, pgup, pgdn keys now auto-repeat
|
||||
- quadrupled the length of the console history
|
||||
- commands:
|
||||
- "game <gamedir>" to load a mod.
|
||||
- "reset <cvar>" to reset a cvar to default. Note that this is the engine default, not the default.cfg value
|
||||
- resetall. resets all cvars.
|
||||
- mods. lists all child folders of quake directory which contain either a progs.dat or a pak file
|
||||
- maps. lists all addon levels available (i.e. all levels that are not in id1/*.pak)
|
||||
- mapname. outputs the short name of the current level (e.g. "e1m5")
|
||||
- cmdlist. alphabetized. 'cmdlist blah' will list only cmds that start with 'blah'
|
||||
- cvarlist. alphabetized. 'cvarlist blah' will list only cvars that start with 'blah'
|
||||
- "inc <cvar> [amount]" to increment a cvar by amount. amount defaults to 1.
|
||||
- "toggle <cvar>" to invert the value of a cvar (nonzero -> 0 and 0 -> 1)
|
||||
- god, noclip, notarget, and fly can now be explicitly set. example: "god 0" will disable god mode
|
||||
- viewpos. outputs (X,Y,Z) pitch yaw roll
|
||||
- "give a <value>" now gives you armour. type depends on value
|
||||
- bindlist. lists all key bindings
|
||||
- "alias <name>" now outputs the current command string
|
||||
- "unalias <name>" to delete an alias
|
||||
- unaliasall. delete all aliases.
|
||||
- condump. dumps console to condump.txt
|
||||
- fog. set global fog. syntax is "fog <density>", "fog <red> <green> <blue>", or "fog <density> <red> <green> <blue>" See section on modding for details. Set density to 0 to disable fog.
|
||||
- "sky <skyname>" to load a skybox. if skyname is "", this will turn off skybox rendering.
|
||||
- stuffcmds now parses the "cmdline" cvar rather than the args actually passed to the program. This is useful for loading mods dynamically, so you can edit the cmdline before execing quake.rc (which calls "stuffcmds")
|
||||
- cvars:
|
||||
- scr_stretch_menus. default 1. if 1, menus and other overlays are stretched to fill the screen
|
||||
- scr_conalpha. default 1. This is the opacity when the console is halfscreen. 0.6 will mimic glquake
|
||||
- scr_clock. default 0. if 1, game time is displayed. If 2, system time is displayed.
|
||||
- scr_showfps. default 0. if 1, FPS are displayed.
|
||||
- r_waterwarp recognized. default 1. if zero, no underwater warping will take place
|
||||
- r_drawflat recognized. default 0. if 1, polygons will be drawn as a solid color with no lightmap or texture
|
||||
- r_particles. default 1. 0 = no particles, 1 = circular particles, 2 = square particles
|
||||
- r_fastsky. default 0. if 1, sky will be rendered as solid color, for added performance
|
||||
- r_sky_quality. default 8. Higher number divides the sky more, for a smoother effect and slower performance.
|
||||
- r_clearcolor now supported. default 2. specify a palette index from 0 to 255.
|
||||
- gl_fullbrights. default 1. set to 0 to disable fullbrights
|
||||
- gl_farclip. default 8192. set to 4096 to mimic glquake. note that the skybox will be drawn somewhat closer than this value.
|
||||
- cl_maxpitch. default 90 (straight down.) set to 80 to mimic normal quake
|
||||
- cl_minpitch. default -90 (straight up.) set to -70 to mimic normal quake
|
||||
- cl_keypad. default 1. if 0, keypad keys will respond as in quake.exe (for example, pushing 'KP_END' will be the same as pushing '1')
|
||||
- gl_flashblend now defaults to 0.
|
||||
- gl_ztrick now defaults to 0.
|
||||
- gl_keeptjunctions now defaults to 1. (note, contrary to the name of this cvar, what is being kept is the extra polygon verts which *eliminate* tjunctions. This is a good thing, so i made it default to 1)
|
||||
- chase_alpha. default 1. lower values make the chasecam player model translucent. Buggy.
|
||||
- keyboard
|
||||
- keypad keys are now bindable:
|
||||
KP_NUMLOCK, KP_SLASH, KP_STAR, KP_MINUS, KP_HOME, KP_UPARROW, KP_PGUP, KP_PLUS, KP_LEFTARROW, KP_5, KP_RIGHTARROW, KP_END, KP_DOWNARROW, KP_PGDN, KP_ENTER, KP_INS, KP_DEL
|
||||
- command line:
|
||||
- running with -gamma at the command line will set the gamma. There is still no way to change this value in game. Default is 1.0 for 3dfx cards, 0.7 for all others
|
||||
- if unspecified, -conwidth now defaults to -width
|
||||
- modding extensions:
|
||||
- skyboxes (worldspawn and qc settable), currently only targa and pcx formats accepted
|
||||
- global fog (worldspawn and qc settable)
|
||||
- physics
|
||||
- fixed sliding around while standing on solid entities' bounding boxes (monsters, players, etc)
|
||||
- misc
|
||||
- default heapsize is now 32mb (was 16mb)
|
||||
- default zonesize is now 256k (was 48k)
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
================================================================================
|
||||
|
||||
Beta release of an SDL port of Fitzquake version 0.80, July 5, 2008
|
||||
|
||||
Author : Kristian Duske
|
||||
Email Address : [email protected]
|
||||
Author's Homepage : http://www.kristianduske.com/fitzquake
|
||||
Minimum SDL version : 1.2.10
|
||||
|
||||
This is a port of the Fitzquake engine to SDL. The main goal of this port is to
|
||||
allow fitzquake to run on all major platforms. Currently there are builds for
|
||||
Windows, Linux and Mac OS X.
|
||||
|
||||
To run this engine, you need to install the SDL and SDL_net library binaries. For
|
||||
Linux, you should probably use the packages for your distribution which should be
|
||||
available through your package manager of choice. The minimum SDL version you
|
||||
need to run this is 1.2.10. On Windows, you can download the SDL and SDL_net dlls
|
||||
from http://www.libsdl.org/. On Mac, the SDL framework is included in the
|
||||
application bundle.
|
||||
|
||||
The Mac OS X version includes a simple launcher program.
|
||||
|
||||
Known issues:
|
||||
- Mouse sensitivity is different than in the original Fitzquake (or vanilla Quake,
|
||||
for that matter).
|
||||
- Pasting from the clipboard does not work.
|
||||
- It is not possible to switch the screen refresh rates from within the engine.
|
||||
- On Linux, there are problems with the default sound sampling rate of 11025Hz.
|
||||
This can be fixed by supplying -sndspeed 48000 on the commandline.
|
||||
|
||||
Changes since the March 7 beta:
|
||||
- discard mouse movement while input is deactivated
|
||||
- implement maps and mods commands using POSIX functions and added a POSIX wrapper
|
||||
for Win32
|
||||
- activate mouse input when binding a key, otherwise mouse keys cannot be bound
|
||||
through the menu
|
||||
- fixed shift key behaviour
|
||||
- implemented TCP networking
|
||||
- fixed fog command (use fmax instead of max in Fog_FogCommand_f)
|
||||
- fixed bug that lead to the screen being set to minimum size when the sizedown
|
||||
command is issued multiple times
|
||||
- LSHIFT + ESC and circomflex always opens the console
|
||||
- print everything to stdout
|
||||
- and more...
|
||||
|
||||
ChangeLog:
|
||||
----------
|
||||
01/22/2008
|
||||
- release mouse pointer when console is active.
|
||||
- enable key repeats (doesn't work on OS X, test in Win32).c
|
||||
|
||||
01/23/2008
|
||||
- implement Sys_SendKeyEvents
|
||||
- disable mouse input when console is inactive using SDL_SetEventFilter
|
||||
- move mouse input processing to main event loop
|
||||
- add vid.mode to determine window mode
|
||||
- fixed Sys_printf()
|
||||
- enable key repeats when console is active only
|
||||
- return 0 if any of the cl_bob vars is 0 in V_CalcBob
|
||||
|
||||
01/24/2008
|
||||
- changed in_deactivate so that it does not always release the mouse cursor
|
||||
- adapted all calls to in_activate and in_deactive, because they need to be called regardless of the current mode
|
||||
- added platform dependent messagebox code for fatal errors on OS X and Windows
|
||||
|
||||
02/06/2008
|
||||
- fixed numlock acting as caps lock issue
|
||||
- fixed: input is not activated on map command (hopefull got them all this time)
|
||||
- center window in windowed modes
|
||||
|
||||
2008/03/14
|
||||
- discard mouse movement while input is deactivated
|
||||
- implement maps and mods commands using POSIX functions and added a POSIX wrapper for Win32
|
||||
- activate mouse input when binding a key, otherwise mouse keys cannot be bound through the menu
|
||||
- fixed shift key behaviour
|
||||
|
||||
2008/06/3
|
||||
- fixed numerous bugs in sdl_net.c
|
||||
|
||||
2008/06/4
|
||||
- fixed fog command (use fmax instead of max in Fog_FogCommand_f)
|
||||
- fixed bug that lead to the screen being set to minimum size when the sizedown command is issued multiple times
|
||||
|
||||
2008/07/4
|
||||
- LSHIFT + ESC and circomflex always opens the console
|
||||
|
||||
2008/07/5
|
||||
- print everything to stdout
|
||||
|
||||
@@ -0,0 +1,532 @@
|
||||
|
||||
================================================================================
|
||||
|
||||
Fitzquake version 0.85, Feb 12, 2009
|
||||
|
||||
Filename : fitzquake085.exe
|
||||
Author : John Fitzgibbons
|
||||
Email Address : [email protected]
|
||||
Author's Homepage : http://www.celephais.net/
|
||||
Fitzquake Homepage : http://www.celephais.net/fitzquake
|
||||
|
||||
Fitzquake is a modified glquake based on the source code released by id
|
||||
Software. My primary focus is fixing a lot of the rendering bugs which made
|
||||
glquake inferior to the software renderer. My secondary focus is adding
|
||||
conveniences for mappers and general users. I am also slowly adding support for
|
||||
new modding or mapping features such as skyboxes, fog, and colored light.
|
||||
|
||||
While I have made extensive changes to the code, I pretty much use the same
|
||||
OpenGL features that the original glquake uses. Therefore, if you can run
|
||||
glquake, you can probably run Fitzquake.
|
||||
|
||||
I am not finished working on this project, so bug reports and feature requests
|
||||
are welcome.
|
||||
|
||||
Acknowlegements
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
id Software, LordHavoc, Bengt Jardrup, Baker, Aardappel, SmallPileOfGibs, FrikaC,
|
||||
Vondur, JPL, Negke, preach, Topaz, Tomaz, Tonik, Radix, EvilTypeGuy, NightBringer,
|
||||
MH, Tyrann, Spirit, Fett, Maddes, Craig Wills, Heffo, Riot, Gleeb, Speedy,
|
||||
people in #flipcode, & others for their feedback, tutorials, code, testing,
|
||||
and assistance.
|
||||
|
||||
Copyright / Permissions
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
|
||||
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.
|
||||
|
||||
History
|
||||
================================================================================
|
||||
|
||||
changes in 0.85
|
||||
---------------
|
||||
- increased limits
|
||||
- added a network protocol 666, which supports higher limits, entity alpha, and more (see command "sv_protocol")
|
||||
- can load and play all known limits-breaking maps, including masque, warpspasm, indian summer, sickbase, 768_negke, digs04, omlabx, and bod.
|
||||
- increased MAX_MODELS from 256 to 2048 (and MAX_MOD_KNOWN from 512 to 2048) (requires the new protocol) Prints a warning if you exceed the old limit.
|
||||
- increased MAX_SOUNDS from 256 to 2048 (requires the new protocol) Prints a warning if you exceed the old limit.
|
||||
- increased the upper limit for the "max_edicts" cvar to 32000 (requires the new protocol for entities past 8192 to play sounds)
|
||||
- models with more than 256 frames can now actually use those frames (requires the new protocol)
|
||||
- fixed crash when marksurfaces > 32767, raising the effective limit to 65k. Prints a warning if you exceed 32767.
|
||||
- fixed crash or other weird behavior when faces > 32767, raising the effective limit to 65k. Prints a warning if you exceed 32767.
|
||||
- fixed crash when nodes > 32767, raising the effective limit for leafs+nodes to 65k. Prints a warning if you exceed 32767.
|
||||
- increased clipnode capacity from 32k to 65k. Prints a warning if you exceed 32767.
|
||||
- increased MAX_MAP_LEAFS from 8192 to 32k (these are visleafs, not total leafs.) Prints a warning if you exceed the old limit.
|
||||
- increased MAX_STATIC_ENTITIES from 128 to 512. Prints a warning if you exceed the old limit.
|
||||
- increased MAX_VISEDICTS from 256 to 1024, which should fix static entities flickering in large maps. Prints a warning if you exceed the old limit.
|
||||
- increased MAX_EFRAGS from 640 to 2048. Should reduce the "Too many efrags!" messages. Prints a warning if you exceed the old limit.
|
||||
- increased MAX_LIGHTMAPS from 64 to 256, meaning you can load 4 times as much lightmap data before getting an "Allocblock:full" error. Prints a warning if you exceed the old limit.
|
||||
- increased MAX_GLTEXTURES from 1024 to 2048
|
||||
- increased MAX_BEAMS from 24 to 32 and MAX_TEMP_ENTITIES from 64 to 256, so you can have more lightning bolts now
|
||||
- increased increase MAX_DLIGHTS from 32 to 64
|
||||
- eliminated "packet overflow" errors in single-player mode on all known maps, by increasing MAX_DATAGRAM from 1024 to 32000 (NET_MAXMESSAGE and MAX_MSGLEN were also increased accordingly.) In multiplayer (including COOP,) the MAX_DATAGRAM size is 1400 because the MTU on most internet routers is ~1450, and anything above this could get fragmented and lost since datagram packets use UDP. Prints warning when packetsize exceeds the standard datagram size.
|
||||
- increased signon buffer capacity, should eliminate sz_getspace errors (example: hard mode coop crash on Travail's qte2m1.bsp.) Prints a warning when signon buffer is too big for standard servers.
|
||||
- "no free edicts" error now spits you back to the console instead of crashing
|
||||
- visual improvements
|
||||
- added model interpolation for animation and movement. See cvars r_lerpmodels, r_lerpmove, r_nolerp_list.
|
||||
- added interpolation on the gun kick motion, and ability to disable gun kick entirely (see cvar "v_gunkick")
|
||||
- disabled torches/bolts casting shadows
|
||||
- more content support
|
||||
- added support for per-entity alpha, and it works even without a custom progs.dat, works on static entities too, and both bsp and mdl models. Set values directly in the map and/or control it with quakec. When setting alpha, a value of "0" is interpreted as "default", which means 1.0 for most things, but for water polygons it t means obey the value of r_waterwarp. A value greater than 0, up to 1.0, will explicitly set the alpha, and override r_wateralpha for water polygons. A value of -1 will explictly set the alpha to 0 (invisible), and override r_wateralpha. (requires the new protocol, except for alpha -1, which makes things invisible even with protocol 15)
|
||||
- can playback protocol 15 demos containing the nonstandard U_TRANS bit, as recorded by nehahra, joequake, and aguirre's engine. When the server says it is running protocol 15, and the U_TRANS bit is encountered, fitzquake will assume it's the Nehahra protocol and parse it accordingly.
|
||||
- added support for -quoth command line switch. Loads quoth content regardless of current gamedir, and enables hipnotic statusbar layout. This allows you to load a mod that requires quoth, but is in a separate directory (i.e. fitzquake.exe -quoth -game warp)
|
||||
- fullbrights now use additive blending instead of alpha blending. This allows me to support external glowmaps, and entity transparency with fullbrights/glowmaps. In some cases, additive fullbrights are rendered using multitexture, but only if GL_EXT_texture_env_add is available. The command line option -nocombine will disable the use of GL_EXT_texture_env_add.
|
||||
- added support for external glowmaps (names must end in _luma or _glow)
|
||||
- added support for external liquid textures (name your files #water instead of *water)
|
||||
- added support for map-specific texture directories (put textures in /textures/mapname/)
|
||||
- interface improvements
|
||||
- improved crosshair accuracy somewhat for protocol 15, and improved it a lot in protocol 666
|
||||
- rearranged scorebar so that map titles as long as 40 chars can be displayed without scrolling
|
||||
- statusbar displayed values now cap at 999 rather than displaying truncated numbers (1001 will be displayed as 999 instead of 001)
|
||||
- tab completion cycle order now alphabetized as a whole rather than grouped by type
|
||||
- added scr_conscale cvar (see below)
|
||||
- added scr_crosshairscale cvar (see below)
|
||||
- added scr_sbaralpha cvar (see below)
|
||||
- scr_showfps and scr_clock display now use same scale as console (scr_conscale, scr_conwidth)
|
||||
- video menu now shows aspect ratio of selected video mode
|
||||
- added aguirRe's trick of making the window perfectly cover the screen with no titlebar/borders, if you create a windowed mode with height/width equal to the desktop size. (not tested on dual monitors, though.)
|
||||
- developer features
|
||||
- added ability to monitor various stats that change dynamically, such as packet size, temp entities, and visedicts. (see cvar "devstats")
|
||||
- restricted spammy messages "packet overflow", "beam list overflow", and "too many efrags" to repeat at most once every 3 seconds
|
||||
- r_showbboxes now draws point entities too
|
||||
- "mcache" command now gives you a total number of models (note, this is a list of all loaded models, not just the current level's model precaches)
|
||||
- "soundlist" command now gives you a total number of sounds (note, this is a list of all loaded sounds, not just the current level's sound precaches)
|
||||
- "give" command can now give armor values above 200
|
||||
- added imagedump command (see below)
|
||||
- "x is not a field" message is now shown only if developer = 1
|
||||
- bugfixes
|
||||
- added Baker's fixes for Intel display adapters
|
||||
- fixed tab completion cycle never reaching certain commands/cvars in list
|
||||
- fixed -dinput mouse doesn't work after vid_restart
|
||||
- fixed rotated alias models incorrectly culled
|
||||
- fixed sky animation on brush models
|
||||
- fixed "invalid pixel format" error when switching between two video modes with the same bit depth, on certain chipsets (Baker had this problem)
|
||||
- fixed alt-tab fullscreen trashed window on some nvidia, intel cards (from Baker)
|
||||
- fixed some TGAs load upside down
|
||||
- fixed non-square PCX loading appears interlaced
|
||||
- fixed PCX loading from inside pakfiles appears as random noise
|
||||
- fixed player skin corruption bug (thanks aguirRe)
|
||||
- fixed improperly trying to colormap the playermodel before a map is loaded, after switching games (could cause a crash or discolored textures)
|
||||
- fixed too-dark fog on world/brushmodels with -nomtex
|
||||
- fixed overbright models too light with fog and -nocombine
|
||||
- fixed r_wateralpha support on brush entities
|
||||
- fixed grenade shadows spinning wildly instead of staying on the ground
|
||||
- fixed solid fogged sky was not quite the same color as solid fogged geometry, for certain colors of fog
|
||||
- fixed trigger_changelevel with missing map causes apparent hang
|
||||
- fixed hang when r_stereo and r_lightmap are both enabled
|
||||
- fixed "W_GetLumpinfo" crash when a graphic is missing from gfx.wad. Prints a console message instead. Missing graphics will be drawn as a checkerboard image. Note: conchars is the one graphic that must be in the gfx.wad, since the console won't even function without it.
|
||||
- fixed accidentally stripping -hipnotic and -rogue directories when switching games
|
||||
- fixed give command doesn't update currentammo
|
||||
- fixed changing gamedirs while a skybox is loaded sometimes corrupts textures/lightmaps in the next map loaded
|
||||
- fixed unnecessary creation of "glquake" subdirectory
|
||||
- fixed 0Hz/0bpp showing up in video menu sometimes
|
||||
- fixed -aliases triggered on alt-tab
|
||||
- fixed con_logcenterprint considering identical messages to be duplicates even though the map has changed in between
|
||||
- fixed hang in proxmap2, when going through one of the teleporters (thanks spirit, mh)
|
||||
- fixed lightning bolt memory corruption crash (rare)
|
||||
- source cleanup
|
||||
- removed all ASM code from source, and removed gas2masm project
|
||||
- cleaned up unnecessary library dependencies in source release
|
||||
- renamed local variable "errno" to fix a compiling problem on visual c++ express edition
|
||||
- added dxsdk folder to source release
|
||||
|
||||
cvars:
|
||||
|
||||
- devstats. default 0. If 1, prints various the current and peak values of various stats that change over time, such as packetsize, and edicts. Note: even if devstats is set to 0, fitzquake will keep track of peak values so when you turn it on, the peaks are accurate. Devstats display scale follows console text scale.
|
||||
|
||||
- r_lerpmodels. default 0. If 1, do interpolation on model animations, with exceptions for torches (r_nolerp_list) & muzzleflares (interpolation is suspended for two frames if EF_MUZZLEFLASH is encountered, on the assumption a muzzleflare happens at the same time.) If 2, lerp all animations, without exception. If 0, disable interpolation (to mimic standard quake.)
|
||||
|
||||
- r_lerpmove. default 0. If 1, do movement interpolation on MOVETYPE_STEP entities (i.e. monsters.) If 0, disable interpolation (to mimic standard quake.) I recommend that you use r_lerpmove and r_lerpmodels together, or turn them both off, otherwise monsters will move strangely.
|
||||
|
||||
- r_nolerp_list. Contains a comma-separated list of filenames of models to exclude from lerping. Filename must include the relative path and extension, for example "progs/flame.mdl". The default is "progs/flame.mdl,progs/flame2.mdl,progs/braztall.mdl,progs/brazshrt.mdl,progs/longtrch.mdl,progs/flame_pyre.mdl,progs/v_saw.mdl,progs/v_xfist.mdl,progs/h2stuff/newfire.mdl". This should include all torches in id1, quoth, and bastion, which look bad when lerped, and the zerstorer chainsaw and xmen fist, which also look bad lerped.
|
||||
|
||||
- r_skyfog. default 0.5. Controls how much the sky is obscured by the fog. 0 = sky is completely unfogged, 1 = sky is completely fogged.
|
||||
|
||||
- scr_conscale. default 1. Scales the console text larger, but only has an effect when scr_conwidth is 0.
|
||||
|
||||
- scr_crosshairscale. default 1. Scales the crosshair larger. 1 = normal, 10 = maximum enlargement
|
||||
|
||||
- scr_sbaralpha. default 1. Controls the transparency of the statusbar background. 0 = invisible, 1 = opaque (original quake behavior), in-between values give different levels of transparency. Pro tip: set it to 0.99 and it will still appear opaque, but the 3D view will expand to fill the area on both sides of the statusbar.
|
||||
|
||||
- v_gunkick. default 1. If 1, standard quake view kick when you fire your gun. If 2, interpolates the view kick. If 0, disables view kick entirely.
|
||||
|
||||
commands:
|
||||
|
||||
- imagedump. Dumps all loaded textures from opengl into tga files. This shows the textures as they exist in opengl texture memory. Texture names containing '*' will be renamed with '#' instead.
|
||||
|
||||
- sv_protocol. Sets the network protocol used by the server. Default is 666. Possible values are 15 (standard netquake protocol) or 666 (new fitzquake protocol.) Changes to the protocol will not take effect until the next time you load/reload a level. When running protocol 666, standard clients won't be able to connect to your server, and they won't be able to play any demos you record. When running protocol 15, only 256 models and 256 sounds can be sent to the client, which means you would see invisible entities and not hear some sounds, when running a map or mod that has more than 256 models or sounds. There is also some other data the server will suppress in protocol 15, such as per-entity alpha. Also note, dzip's special demo compression does not work on demos that use modified protocols, so you will get a compression ratio no better than standard zip compression.
|
||||
|
||||
changes in 0.80
|
||||
---------------
|
||||
|
||||
- map loading is about four times faster. This is due to some optimizations in the texture loading code.
|
||||
- video mode can now be changed in-game. You can change resolution, color depth, refresh rate, and switch between windowed and fullscreen modes. This can be accomplished easily using the video options menu, and is also available at the console using cvars. Note: if you launch fitzquake with -width, -height, -window, or -bpp in the command line, Fitzquake will use the command line settings and ignore whatever it reads from the config files at startup. However, you will still be able to change the video mode from the menu or the console as you like. Also note: to change video modes by execing a config file, the config file must include "vid_restart" after the other vid_ cvars have been set. (see cvars "vid_width," "vid_height," "vid_fullscreen," "vid_bpp," "vid_refreshrate," and commands "vid_restart," "vid_test")
|
||||
- added control of entity count limits (MAX_EDICTS.) The default maximum has been increased from 600 to 1024. It can be raised even higher (up to 8192 -- this is a limit set by the network protocol) using a cvar. (see cvar "max_edicts")
|
||||
- added control of vertical sync. (see cvar "vid_vsync")
|
||||
- added control of anistropic filtering. Anisotropic filtering is a method to improve texture clarity on surfaces when viewed at steep angles. (see cvar "gl_texture_anisotropy")
|
||||
- console buffer size can now be set. The command line option "-consize" allows you to specify the buffer size in kilobytes. For reference, fitzquake's default buffer size is 64k, and glquake's is 16k. 16k is also the smallest size fitzquake will allow you to set. Note: this buffer lives in the heap, so if you want to have a HUGE buffer, you might need to increase -heapsize also.
|
||||
- increased max surface extents from 256 (the software quake maximum) to 2000. For reference, the glquake maximum is 512. This should eliminate the "bad surface extents" crash when running some maps that could be played in glquake, but not fitzquake or winquake.
|
||||
- increased max vertices in an alias model from 1024 (the glquake maximum) to 2000 (the software quake maximum.)
|
||||
- increased MAX_CHANNELS from 128 to 512 and MAX_DYNAMIC_CHANNELS from 8 to 128
|
||||
- screenshot filenames are now in the format "fitz0000.tga", increasing the maximum number of screenshots per folder from one hundred to ten thousand.
|
||||
- vid_describemodes output cleaned up; now displays a list of valid refresh rates for each mode
|
||||
- added a more intuitive cvar control of slow motion/fast-forward for demos and live gameplay. (see cvar "host_timescale")
|
||||
- "reset to defaults" option in the menu now executes the "resetall" command before loading default.cfg
|
||||
- game command now writes config.cfg to current gamedir before switching
|
||||
- +mlook is now saved to config.cfg
|
||||
- changed smallest allowed window size from 320x240 to 320x200
|
||||
- console cursor images are now hard-coded, and the insert mode cursor is now a vertical bar instead of an underscore. This was prompted by several popular mods (OUM, Xmen TC) using nonstandard cursors, which are incompatible the fitzquake console enhancements.
|
||||
- gl_farclip now defaults to 16384. This should be high enough to handle even the largest open areas without unwanted clipping. The only reason you'd want to lower this number is if you see z-fighting.
|
||||
- added cvar r_drawworld (see below)
|
||||
- added cvar r_showtris (see below)
|
||||
- added cvar r_showbboxes (see below)
|
||||
- added a command to cycle a cvar through a list of values. (see command "cycle")
|
||||
- mapname command now works on dedicated server.
|
||||
- added a hack to fix those white edges on the bottom of the large box of shells. I feel dirty, but they look better, now.
|
||||
- changed stuffcmds behavior to allow hyphenated map names, config file names, etc. in the command line. (example: "fitzquake.exe +exec my-config.cfg +map my-map") However, you still can't load a map or config file when the first character in the filename is a hyphen.
|
||||
- skybox loader now reverts to scrolling sky if all 6 skybox faces failed to load.
|
||||
- tweaked circular particles to match the apparent size of the square particles.
|
||||
- fixed crash when loading mods with large player skins (like the chainsaw mod, and PerQuake.) Colormapping can now handle any size player texture (limited to the heapsize, of course.)
|
||||
- fixed bug where a replacement model in a mod is messed up becuase a matching .ms2 file in id1/glquake is present. The fix is simply to disable all mesh caching, which slows down model loading a little.
|
||||
- fixed freeze when gl_overbright is 1 and either texture_env_combine or multitexture is disabled or not supported.
|
||||
- fixed "numgltextures == MAX_GLTEXTURES" crash when viewing multiplayer->setup menu.
|
||||
- fixed "numgltextures == MAX_GLTEXTURES" crash when playing large maps (nesp09,) due to frequent model recaches.
|
||||
- fixed bug where entities and water were not being drawn any frame in which a model had to be recached.
|
||||
- fixed skybox texture showing up in the place of other textures/skins/lightmaps, when the previous loaded map had a skybox.
|
||||
- fixed missing polygons on edges of screen when underwater and r_waterwarp is 1.
|
||||
- fixed missing polygons on edges of screen when r_stereo is enabled.
|
||||
- fixed long mapnames that scroll are truncated to be shorter than what appears in the console. Well, sort of. What I did was increase the maximum length from 39 to 127. A mapname longer than 127 will still be truncated, but these are pretty rare.
|
||||
- fixed rogue's teamplay skin showing up as an all-white texture.
|
||||
- fixed checkerboard texture shows up sometimes when an animated texture has fullbright pixels on some frames, but not others (reactor core in junk.bsp)
|
||||
- fixed color 255 is not fullbright
|
||||
- fixed fuscia dots appearing in corners of resampled textures
|
||||
- fixed mapname command crashes when client is disconnected.
|
||||
- fixed cl_nolerp 1 screws up speed of demo playback
|
||||
- fixed annoying client-side step-up smoothing when in noclip mode (except on nonlocal servers.)
|
||||
- fixed scr_clock 2 displays hour twelve as "0" instead of "12"
|
||||
- fixed skip textured surfaces still drawn even after running tyrann's skip utility
|
||||
- fixed crash when loading a map with a sky texture where the "sky" in the texturename is not lowercase
|
||||
- fixed hang in e2m2 on easy skill, where you can shoot one of the buttons at the beginning and then trick-jump through the open gate. Now it prints a warning message ("SV_TouchLinks: null link") and lets you keep playing.
|
||||
- fixed bug when viewsize < 100, and r_oldwater is 0, where you can see the water textures overlaying part of the brown frame around the viewport.
|
||||
- fixed bug where imagelist and r_speeds2 would report the same megabyte counts in both 16bpp and 32bpp mode, even though texture bpp should match (and does match) framebuffer bpp. The numbers are now different and accurate for each bit depth.
|
||||
- removed cvars "vid_config_x," "vid_config_y," "vid_wait," "vid_nopageflip," "_vid_wait_override," "_vid_default_mode," "_vid_default_mode_win," and "vid_stretch_by_2," none of which glquake ever used.
|
||||
- removed cvar "vid_mode" and commands "vid_describemode" and "vid_nummodes," because of the new video mode handling.
|
||||
|
||||
cvars:
|
||||
|
||||
- gl_texture_anisotropy. Controls the amount of anisotropy in texture filtering. If 1 or less than 1, texture filtering is normal (isotropic.) If greater than 1, increasing degrees of anisotropic filtering are used, up to the hardware maximum. Set value to 2 for 2x anisotropic, 4 for 4x, etc. Default 1.
|
||||
|
||||
- host_timescale. Scales the passage of time on client and server. Set to 0 or 1 for normal speed, less than 1 for slow motion, and greater than 1 for fast-forward. If greater than 0, overrides host_framerate. Default 0.
|
||||
|
||||
- max_edicts. Sets the maximum number of entites on both the client and server. Default 1024. Acceptable values range from 256 to 8192. Set to 600 to mimic standard quake. Changes won't take effect until the next time a map is loaded. Note: if a client connects to a server, and the client's maximum is lower than the server's, the client will probably crash if it ever sees an entnum higher than its local max_edicts. Warning: you may need to increase -heapsize if you want a high max_edicts value.
|
||||
|
||||
- r_drawworld. If 1, draw world as usual. If 0, don't draw the world. Default 1. (compare r_drawentities)
|
||||
|
||||
- r_showbboxes. If 1, draw a wireframe bounding box around each entity. Note that these are the server-side per-edict physics bounding boxes, not the client-side per-model rendering bboxes. If 0, disable this feature. Default 0.
|
||||
|
||||
- r_showtris. If 1, draw wireframe outlines for every triangle in the scene. Like in Quake 3, the lines will be visible even through solid geometry. If 2, draw the outlines only on visible surfaces (like r_showtris 2 in Medal of Honor.) If 0, disable wireframe overlay. Default 0.
|
||||
|
||||
- vid_bpp. Sets the color depth of the screen in fullscreen mode. Windowed mode ignores this setting. Can be 16 or 32. Default 16. (Changes won't take effect until the next call to vid_restart.)
|
||||
|
||||
- vid_fullscreen. If 1, fitzquake will run fullscreen. If 0, fitzquake will run in a window. Default 1. (Changes won't take effect until the next call to vid_restart.)
|
||||
|
||||
- vid_height. Sets the vertical screen/window resolution. Default 480. In windowed mode, cannot be less than 200. (Changes won't take effect until the next call to vid_restart.)
|
||||
|
||||
- vid_refreshrate. Sets the refresh rate of the screen in fullscreen mode. Windowed mode ignores this setting. Possible values include 60, 70, 72, 75, 85, etc. Default 60. (Changes won't take effect until the next call to vid_restart.)
|
||||
|
||||
- vid_width. Sets the horizontal screen/window resolution. Default 640. In windowed mode, cannot be less than 320. (Changes won't take effect until the next call to vid_restart.)
|
||||
|
||||
- vid_vsync. Set to 1 to enable vertical sync, which eliminates tearing, but caps your framerate at the monitor refreshrate. Set to 0 to disable vertical sync, which allows tearing but doesn't cap your framerate. Default 0. Note: If fitzquake detects that your driver settings have forced vsync to be disabled, it will post a message to the console saying so, and this cvar will have no effect.
|
||||
|
||||
commands:
|
||||
|
||||
- "cycle <cvar> <value> [<value> [<value> ...]]" to cycle a cvar through a list of values.. Note: this command will get stuck on a list that contains the same value more than once, such as "cycle blah 1 2 1 3". If you're doing anything that complex you can just use aliases.
|
||||
|
||||
- vid_restart. Tries to set a video mode that matches the values of vid_width, vid_height, vid_fullscreen, and, if vid_fullscreen is 1, vid_bpp and vid_refreshrate.
|
||||
|
||||
- vid_test. Like vid_restart, except that after switching to the new mode pops up a confirmation dialogue. This is useful if you are not sure what modes your monitor can handle, so you don't get stuck with a blank screen. The dialogue has a time limit so that if you don't press a key within 5 seconds, it will revert to the previous mode.
|
||||
|
||||
changes in 0.75
|
||||
---------------
|
||||
|
||||
- totally rewritten bsp drawing code. The new code combines the advantages of the gl_texsort 1 and gl_texsort 0 codepaths from glquake into one codepath that uses texture sorting and multitexture. In my tests, i've found that it's about the same speed as glquake in low poly scenes (like the original quake levels,) but as you get into the thousands of wpolys, it's faster and faster.
|
||||
- 2x overbright lighting. Lighting now looks like software quake. Just like overbright lighting on models, overbright on world polys requires GL_EXT_texture_env_combine (TNT and later, voodoo4 and later.) Without it, FitzQuake will be use two passes to render overbright world polys. So if you don't have that extension, you might disable it for performance reasons. (see cvar "gl_overbright")
|
||||
- colored lighting support using .lit files.
|
||||
- totally new water surface animation. The new method requires no surface subdivision, isn't plagued by tearing and sparklies caused by tjunctions, and looks almost identical to software quake's water, and doesn't slow down on very large sheets of water. (see cvars "r_waterquality" and "r_oldwater")
|
||||
- old water aninmation fixed so that it doesn't look bad when gl_subdivide_size is 32 or lower.
|
||||
- can load external textures (currently targa and pcx) if they match the texture name in the bsp and are located in the id1/textures, or <MODDIR>/textures directory. At the moment no other images (skins, menu, etc.) can be replaced.
|
||||
- gamma correction now goes back to normal when Fitzquake loses focus.
|
||||
- tab completion now adds a space after the completed command/cvar if the cursor is at the end of the editline.
|
||||
- increased the max length of the video mode list from 30 to 80. This should alleviate the problems people with newer cards were having trying to use some 32-bit modes -- there were so many 16-bit modes that they filled up the list before all 32-bit modes could be detected. The video menu will still only list a certain number of modes due to space constraints, but you can see the complete list by using the console command "vid_describemodes"
|
||||
- number of listed video modes in the "video options" menu increased from 27 to 36.
|
||||
- added alpha control for the front sky layer. (see cvar "r_skyalpha")
|
||||
- clock can now display time in 24-hour or "military" time.
|
||||
- added an "mtex" counter to the r_speeds 2 readout. This measures the number of megabytes of texture memory used each frame to draw the scene. Note: this doesn't count textures used to draw the console, menu, or statusbar.
|
||||
- added optional drawing of surfaces inside sky leaves, for compiler/map testing purposes. (see cvar "r_oldskyleaf")
|
||||
- sky surfaces on bmodels are now visible, though drawn incorrectly.
|
||||
- fixed multiple textures in bsp with same name or no name get overwritten/not loaded. (example: rd1m3)
|
||||
- fixed some nasty texture loading bugs that were especially hounding 3dfx users (wrong texture, no texture, or unnecessarily low-res textures displayed on models and world.) These bugs would also occur in conjunction with nonzero values of gl_max_size or gl_picmip.
|
||||
- fixed bug where changing gl_max_size or gl_picmip in-game would screw up alias model texture coordinates.
|
||||
- fixed bug where if -gamma is specified at the command line, the "gamma" cvar would be ignored.
|
||||
- fixed model more than 2048 units above floor us unlit by static lighting.
|
||||
- fixed crash with con_logcenterprint when centerprint message was too long.
|
||||
- fixed crash when changing to a nonexistant gamedir and then trying to write a file (screenshot, etc.) Fitzquake now creates the directory as needed.
|
||||
- fixed "bad surface extents" error when sky or water surface is missing from bsp file.
|
||||
- fixed alias model shadows write to z-buffer.
|
||||
- fixed underwater intermission camera has warp, but no screenblend.
|
||||
- fixed console buffer still scrolled back after using the "clear" command.
|
||||
- fixed console command history (the list of previous commands) not being rewound after toggling the console.
|
||||
- removed cvar gl_texsort. New bsp drawing code always sorts by texture.
|
||||
- removed cvar gl_ztrick. The depth buffer is now cleared every frame.
|
||||
- removed cvar gl_keeptjunctions. Extra verts created by qbsp to eliminate tjunctions are now always kept.
|
||||
- removed "sliding on monsters' heads" fix, becuase I decided I don't like the idea of changing gameplay, even if the original behaviour is clearly a bug. Since this bug can be fixed in quakec also, I feel safer leaving it as it was.
|
||||
|
||||
cvars:
|
||||
|
||||
- gl_overbright. default 1. This variable controls overbright lighting on the world polygons. (For lighting on models, use gl_overbright_models.) If 1, overbright will be enabled and lighting will resemble software Quake. If 0, overbright will be disabled and lighting will resemble GLQuake.
|
||||
|
||||
- r_oldskyleaf. default 0. If 0, surfaces inside sky leaves will be skipped by the renderer. If 1, they will be drawn whenever they are in your PVS, just like any other surface.
|
||||
|
||||
- r_oldwater. default 1. If 1, use the old GLQuake method of subdividing the water surface to enable a warping animation. If 0, use the new render-to-texture method. Note: in general, r_oldwater 0 looks better and runs slower. So experiment to see if the performance hit is acceptable to you.
|
||||
|
||||
- r_skyalpha. default 1. Sets the alpha of the front sky layer. Note that if sky alpha is less than 1.0, the sky will be drawn in two passes even if you have multitexture.
|
||||
|
||||
- r_waterquality. default 8. Sets the quality of the water when r_oldwater is 0. Can be anywhere from 1 to 64. Lower values give better performance, higher values look better. A value of 4 will provide water that looks at least as good as glquake can get, and 32 is close enough to software quake for all but the most picky. To control the quality of water when r_oldwater is 1, use gl_subdivide_size instead.
|
||||
|
||||
- scr_clock. default 0. If 1, game time is displayed. If 2, system time is displayed in 12-hour format. If 3, system time will be displayed in 24-hour or "military" time.
|
||||
|
||||
Changes in 0.70
|
||||
---------------
|
||||
|
||||
- added anaglyph stereo rendering. Note that this will cut your framerate in half, as it is rendering the scene once for each eye. You might want to turn off r_drawviewmodel as it is hard to focus on becuase it is so close. (see cvars "r_stereo", "r_stereodepth")
|
||||
- now uses ARB_multitexture if present, otherwise tries to use SGIS_multitexture. This should fix various blending bugs on some cards, such as weird cloud layers, all-black models, and inverted torches. (only ARB guarantees that GL_DECAL blending will work)
|
||||
- overbright models now uses GL_EXT_texture_env_combine if supported (TNT and later, voodoo4 and later,) which saves one or two passes on model rendering when gl_overbright_models is 1. The command line option -nocombine will disable this.
|
||||
- gl_overbright_models now defaults to 1
|
||||
- custom palettes are now correctly loaded when you use the "game" command.
|
||||
- RecursiveLightPoint is now lerped for smoother lighting of slow-moving models. Check out the ogre in e3m3 for an example.
|
||||
- dynamic lighting (rockets, etc) has been moderately sped up. (some lightmaps were being uploaded even though they weren't actually touched by a dynamic light.)
|
||||
- overhauled 2d drawing to allow independent scaling of console, menu, and sbar (see cvars "scr_conwdith," "scr_menuscale," and "scr_sbarscale") command line switches "-conwidth" and "-conheight" removed. cvar "scr_stretch_menus" removed.
|
||||
- user control of max framerate. (see cvar "host_maxfps")
|
||||
- improved the accuracy of the FPS counter a bit, but it still seems suspect.
|
||||
- particles can now be drawn as quads or triangles. (see cvar "r_quadparticles")
|
||||
- opengl information (vendor, renderer, version, extensions) is no longer printed during initialization. (see command "gl_info")
|
||||
- rewrote texture management. Now instead of quake's memory usage going up and up forever (becuase textures were uploaded to the opengl.dll and never freed,) all textures will get flushed when you switch games, bringing you back down to where you were when fitzquake first launched.
|
||||
- gl_texturemode command will now accept a number (1 through 6) as well as the name (gl_linear_mipmap_nearest, etc.)
|
||||
- gl_describetexturemodes will list all texturemodes.
|
||||
- the inside of sky leaves are no longer rendered -- so when noclipping inside them, it will look the same as noclipping inside a solid wall. This does not affect gameplay.
|
||||
- cleaned up intermission display in singleplayer -- no more overlapping numbers
|
||||
- r_speeds readout modified a bit. (see cvar "r_speeds")
|
||||
- r_sky_quality now defaults to 12 instead of 8, since skies are now drawn in 1 pass (with multitexture at least)
|
||||
- gl_texsort now always defaults to 0. (it used to be forced to 1 when multitexture was unavailable)
|
||||
- fixed bug where models would actually darken when dlights got bright enough
|
||||
- fixed deathmatch, coop cvars not reset to zero when starting a new game from the single player menu
|
||||
- fixed r_lightmap doesn't work when gl_texsort = 0.
|
||||
- fixed inverted lightmaps / no textures / no dynamic light bug when multitexture is disabled and gl_texsort = 0
|
||||
- fixed scrolling map title in wrong place when width does not equal conwidth
|
||||
- fixed a few color borking problems in 16-bit mode. The front sky layer, sprites, and pics with transparency will still look a bit off (as in glquake,) but at least the console image and statusbar background look better. Though it isn't perfect, it should once again look like what you expect from glquake in 16bit.
|
||||
- fixed pixel gap on both sides of the console in 1024x768
|
||||
- fixed wpoly count being slightly lower when gl_texsort = 0 (the count was correct when gl_texsort = 1)
|
||||
- fixed lmap count always zero when gl_texsort = 1
|
||||
- dlight fans are now drawn after water, so that it looks right at least when wateralpha is 1.
|
||||
- fixed a possible bug with older 3dfx cards (voodoo 1/2/rush) where the gamma cvar might not work (untested)
|
||||
- fixed old commands showing up in the console prompt after hitting 'enter'
|
||||
- increased MAX_HANDLES so that you should never see the "out of handles" error message.
|
||||
- removed cvar "chase_alpha." the transparent player model was buggy and didn't work well in a lot of conditions.
|
||||
- removed cvar "gl_doubleeys" (yes, that is the correct misspelling) With overbright models, eyes can be seen as easily as in software mode.
|
||||
- removed cvars "cl_crossx," "cl_crossy," "lcd_x," "lcd_yaw," and "gl_reporttjunctions" which didn't do anything (in glquake, at least).
|
||||
- removed support for GL_EXT_shared_texture_palette (special 8-bit texture format)
|
||||
- removed VCR code. command line switches "-record" and "-playback" no longer supported.
|
||||
- removed support for command line switch "-gamma" -- just use the gamma cvar, or idgamma or something.
|
||||
|
||||
cvars:
|
||||
|
||||
- r_stereo. default 0. If nonzero, the scene will be rendered once in red, and again in cyan, with the two views shifted slightly. If you have 3D glasses you can appreciate this (assumes that the left eye is red and the right eye is cyan.) The value of r_stereo sets the eye separation. If your glasses have red on the right eye, use a negative value to flip the views.
|
||||
|
||||
- r_stereodepth. default 128. Sets the distance at which the two views will converge when stereo rendering is active.
|
||||
|
||||
- scr_conwdith. default 0. Sets the virtual console width, where smaller numbers means larger text. Values larger than window width, or smaller than 320, will be clamped to that range, and all values will be rounded to a multiple of 8. If 0, the window width will be used. Note that values that divide evenly into the window width will make the text look nicest.
|
||||
|
||||
- scr_menuscale. default 1. Sets the scale factor for menus and other centered overlays. If 1, images will be drawn at 1:1 scale. If 2, images will be double size. Menus will never be drawn smaller than 1:1, and never larger than the size of the window. Note that integer values will make the text look nicest.
|
||||
|
||||
- scr_sbarscale. default 1. Sets the scale factor for the statusbar. If 1, images will be drawn at 1:1 scale. If 2, images will be double size. The statusbar will never be drawn smaller than 1:1, and never larger than the width of the window. Note that integer values will make the text look nicest.
|
||||
|
||||
- host_maxfps. default 72. sets the maximum frames per second fitzquake will render (also the maximum number of server frames per second.) Clamped to the range 10 - 1000. Set to 72 to mimic standard quake.
|
||||
|
||||
- r_quadparticles. default 1. If 1, particles are drawn as GL_QUADS instead of GL_TRIANGLES. Quads use 4 verts instead of 3, but the fillrate cost is 1/2 that of triangles. Depending on your card, either one may be faster. This cvar has no effect on the appearance of particles.
|
||||
|
||||
- r_speeds. default 0. Values of 1 and 2 will give you increasing amounts of information. When you see two numbers separated by a slash, the first number is polys, and the second number is passes.
|
||||
|
||||
commands:
|
||||
|
||||
- gl_info. Displays opengl info which was previously displayed during initialization: vendor, renderer, version, and extensions
|
||||
|
||||
- imagelist. Displays a list of loaded textures, and their dimentions.
|
||||
|
||||
- gl_texturemode. Now accepts a number (1 through 6) as well as the name (gl_nearest, etc.)
|
||||
|
||||
- gl_describetexturemodes. Lists all texturemodes.
|
||||
|
||||
Changes in 0.65
|
||||
---------------
|
||||
|
||||
- gamma cvar now supported. (see cvar "gamma")
|
||||
- fullbrights on models now supported.
|
||||
- odd-sized world textures are now bilinearly resampled (instead of glquake's nearest pixel resample)
|
||||
- removed all fixed-size buffers for loading textures; now the only limit is the size of your memory heap (textures will still be downsampled if they are bigger than the hardware can handle)
|
||||
- styled lights (torch flicker, etc.) can now be disabled (see cvar "r_flatlightstyles")
|
||||
- sky now uses multitexture if available.
|
||||
- centerprints are now optionally logged to the console (see cvar "con_logcenterprint")
|
||||
- number of savegame slots increased to 20 (from 12)
|
||||
- if a map title is longer than 22 characters, it scrolls marquee-style in the statusbar.
|
||||
- gl_flashblend defaults to 1 again. (consistency with glquake)
|
||||
- gl_ztrick defaults to 1 again. (consistency with glquake)
|
||||
- command line gamma now defaults to 1.0 for all cards. (consistency with glquake, plus hardware gamma is better)
|
||||
- now checks hardware for maximum texture size. Users of later voodoo cards should be able to see large textures now. (see cvar "gl_max_size")
|
||||
- now shows AM/PM when scr_clock is 2
|
||||
- fixed crash when starting dedicated server
|
||||
- fixed crash when loading too many textures. (now it throws a sys_error and quits)
|
||||
- fixed fitzquake-specific crash when player goes near water in a demo playback.
|
||||
- scr_conalpha now actually works.
|
||||
- keypad enter in the console works again.
|
||||
- optional 2x overbrightening on models. (see cvar "gl_overbright_models")
|
||||
- optional quake2-style noclip. (see cvar "sv_altnoclip")
|
||||
- new icon
|
||||
|
||||
cvars:
|
||||
|
||||
- con_logcenterprint: If 1, centerprint messages will be logged to the console in sp/coop. If 2, they will also be logged in deathmatch. Default 1.
|
||||
|
||||
- gamma: Brighten or darken the screen to compensate for differences between monitors. This is now supported by using your video card's gamma support. Just like in winquake, values less than 1 are brighter and values greater than one are darker. Default 1. Notes: I have added special code so that this will work on 3dfx cards too, but i have no way to check that it works. If fitzquake crashes, your hardware gamma may be stuck at the wrong value. You can use the "display settings" control panel fix this, or you could try lordhavoc's useful "setgamma" utility (available on this page.) Also note that if texture-brightening gamma has been requested at the command line (fitzquake.exe -gamma ), harware gamma will not be used and the gamma cvar will have no effect.
|
||||
|
||||
- gl_max_size: Now defaults to 0. If 0, textures will be as large as the hardware allows. Positive values can be used to impose a limit smaller than the hardware's reported maximum.
|
||||
|
||||
- gl_overbright_models: If 1, models will be rendered using 2x overbrightening and will appear at roughly the same brightness as they do in software quake, which is noticably brighter than the default fitzquake / glquake appearance. I disabled this cvar by default becuase this is still a poorly supported feature -- it currently takes 2 or 3 passes to render a model when this feature is enabled, compared to only 1 pass when it is disabled. Default 0.
|
||||
|
||||
- r_flatlightstyles: If 1, styled lights (torch flicker, etc.) will be displayed as a steady light. If 2, the peak intensity will be used instead of the average intensity. Default 0.
|
||||
|
||||
- sv_altnoclip: If 1, enable the alternative noclip movement which resembles quake2 and is not constrained to the horizontal plane. Set to 0 to retain quake's original noclip behavior. Default 1.
|
||||
|
||||
Changes in 0.60
|
||||
---------------
|
||||
|
||||
- graphics:
|
||||
- better sky projection, configurable for performance
|
||||
- menus and other overlays are now centered on the screen, and can optionally stretch to fit resolution.
|
||||
- all 2d graphics now obey gl_texturemode and all texturemode changes take effect immediately
|
||||
- underwater warping now resembles quake3's perspective munging, and obeys r_waterwarp
|
||||
- fixed frustum culling b0rked (giving HOM at certain FOV / vidsize / screensize combinations)
|
||||
- fixed lack of support for VP_PARALLEL_ORIENTED, VP_PARALLEL_UPRIGHT, and FACING_UPRIGHT sprites
|
||||
- fixed fullbrights not displayed on world/bmodels
|
||||
- fixed texture cache mismatch error
|
||||
- fixed pink edges on sprites, menu items, etc
|
||||
- fixed particle z-buffer bug (apparent when a particle is in front of a water surface)
|
||||
- fixed ugly resampling of non-power of two gfx, skins, sprites
|
||||
- fixed large models (shamblers, shub) dissapearing near edge of screen
|
||||
- fixed statusbar not visible when gl_clear = 1
|
||||
- fixed r_fullbright change not immedate when gl_texsort = 0
|
||||
- fixed alias models still dark when r_fullbright = 1
|
||||
- fixed HOM when screen is partially underwater
|
||||
- fixed gunshot decals not showing up on some walls
|
||||
- sky and water warp now freeze when you pause, as well as lightning bolts
|
||||
- r_novis changes now take effect immediately, rather than when you cross a leaf boundary
|
||||
- removed mirror code
|
||||
- two particle styles, circle and square (cvar controlled)
|
||||
- console:
|
||||
- improved tab completion:
|
||||
- hitting tab once will display a list of possible matches and complete the line using the first match
|
||||
- hitting tab or shift-tab will cycle through the matches
|
||||
- autocomplete will now match against aliases as well as commands and cvars.
|
||||
- autocomplete will now complete later in the string (e.g. "bind mouse1 +att" + tab will complete '+attack')
|
||||
- autocomplete will even complete inside the string (e.g. "bind m +attack" + tab will complete 'mouse1' if the cursor is right after the 'm')
|
||||
- new key functionality:
|
||||
- tab -- autocomplete, cycle through multiple matches
|
||||
- shift-tab -- cycle backwards through multiple matches
|
||||
- ins -- toggle insertmode
|
||||
- del -- delete current character
|
||||
- backspace -- delete previous character
|
||||
- ctrl-v -- paste from windows clippboard
|
||||
- leftarrow -- move cursor one character left in line
|
||||
- rightarrow -- move cursor one character right in line. or, get one character from the previous command.
|
||||
- home -- move cursor to beginning of line
|
||||
- end -- move cursor to end of line
|
||||
- ctrl-pgup -- scroll up a screen at a time
|
||||
- ctrl-pgdn -- scroll down a screen at a time
|
||||
- ctrl-home -- scroll to top of console history
|
||||
- ctrl-end -- scroll to bottom of console history
|
||||
- carets indicate that you are scrolled back, like in quakeworld/quake2
|
||||
- left arrow, right arrow, pgup, pgdn keys now auto-repeat
|
||||
- quadrupled the length of the console history
|
||||
- commands:
|
||||
- "game <gamedir>" to load a mod.
|
||||
- "reset <cvar>" to reset a cvar to default. Note that this is the engine default, not the default.cfg value
|
||||
- resetall. resets all cvars.
|
||||
- mods. lists all child folders of quake directory which contain either a progs.dat or a pak file
|
||||
- maps. lists all addon levels available (i.e. all levels that are not in id1/*.pak)
|
||||
- mapname. outputs the short name of the current level (e.g. "e1m5")
|
||||
- cmdlist. alphabetized. 'cmdlist blah' will list only cmds that start with 'blah'
|
||||
- cvarlist. alphabetized. 'cvarlist blah' will list only cvars that start with 'blah'
|
||||
- "inc <cvar> [amount]" to increment a cvar by amount. amount defaults to 1.
|
||||
- "toggle <cvar>" to invert the value of a cvar (nonzero -> 0 and 0 -> 1)
|
||||
- god, noclip, notarget, and fly can now be explicitly set. example: "god 0" will disable god mode
|
||||
- viewpos. outputs (X,Y,Z) pitch yaw roll
|
||||
- "give a <value>" now gives you armour. type depends on value
|
||||
- bindlist. lists all key bindings
|
||||
- "alias <name>" now outputs the current command string
|
||||
- "unalias <name>" to delete an alias
|
||||
- unaliasall. delete all aliases.
|
||||
- condump. dumps console to condump.txt
|
||||
- fog. set global fog. syntax is "fog <density>", "fog <red> <green> <blue>", or "fog <density> <red> <green> <blue>" See section on modding for details. Set density to 0 to disable fog.
|
||||
- "sky <skyname>" to load a skybox. if skyname is "", this will turn off skybox rendering.
|
||||
- stuffcmds now parses the "cmdline" cvar rather than the args actually passed to the program. This is useful for loading mods dynamically, so you can edit the cmdline before execing quake.rc (which calls "stuffcmds")
|
||||
- cvars:
|
||||
- scr_stretch_menus. default 1. if 1, menus and other overlays are stretched to fill the screen
|
||||
- scr_conalpha. default 1. This is the opacity when the console is halfscreen. 0.6 will mimic glquake
|
||||
- scr_clock. default 0. if 1, game time is displayed. If 2, system time is displayed.
|
||||
- scr_showfps. default 0. if 1, FPS are displayed.
|
||||
- r_waterwarp recognized. default 1. if zero, no underwater warping will take place
|
||||
- r_drawflat recognized. default 0. if 1, polygons will be drawn as a solid color with no lightmap or texture
|
||||
- r_particles. default 1. 0 = no particles, 1 = circular particles, 2 = square particles
|
||||
- r_fastsky. default 0. if 1, sky will be rendered as solid color, for added performance
|
||||
- r_sky_quality. default 8. Higher number divides the sky more, for a smoother effect and slower performance.
|
||||
- r_clearcolor now supported. default 2. specify a palette index from 0 to 255.
|
||||
- gl_fullbrights. default 1. set to 0 to disable fullbrights
|
||||
- gl_farclip. default 8192. set to 4096 to mimic glquake. note that the skybox will be drawn somewhat closer than this value.
|
||||
- cl_maxpitch. default 90 (straight down.) set to 80 to mimic normal quake
|
||||
- cl_minpitch. default -90 (straight up.) set to -70 to mimic normal quake
|
||||
- cl_keypad. default 1. if 0, keypad keys will respond as in quake.exe (for example, pushing 'KP_END' will be the same as pushing '1')
|
||||
- gl_flashblend now defaults to 0.
|
||||
- gl_ztrick now defaults to 0.
|
||||
- gl_keeptjunctions now defaults to 1. (note, contrary to the name of this cvar, what is being kept is the extra polygon verts which *eliminate* tjunctions. This is a good thing, so i made it default to 1)
|
||||
- chase_alpha. default 1. lower values make the chasecam player model translucent. Buggy.
|
||||
- keyboard
|
||||
- keypad keys are now bindable:
|
||||
KP_NUMLOCK, KP_SLASH, KP_STAR, KP_MINUS, KP_HOME, KP_UPARROW, KP_PGUP, KP_PLUS, KP_LEFTARROW, KP_5, KP_RIGHTARROW, KP_END, KP_DOWNARROW, KP_PGDN, KP_ENTER, KP_INS, KP_DEL
|
||||
- command line:
|
||||
- running with -gamma at the command line will set the gamma. There is still no way to change this value in game. Default is 1.0 for 3dfx cards, 0.7 for all others
|
||||
- if unspecified, -conwidth now defaults to -width
|
||||
- modding extensions:
|
||||
- skyboxes (worldspawn and qc settable), currently only targa and pcx formats accepted
|
||||
- global fog (worldspawn and qc settable)
|
||||
- physics
|
||||
- fixed sliding around while standing on solid entities' bounding boxes (monsters, players, etc)
|
||||
- misc
|
||||
- default heapsize is now 32mb (was 16mb)
|
||||
- default zonesize is now 256k (was 48k)
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
-- from quake retexturing project
|
||||
|
||||
diff --git a/Quake/gl_model.c b/Quake/gl_model.c
|
||||
index 239d361..80948f1 100644
|
||||
--- a/Quake/gl_model.c
|
||||
+++ b/Quake/gl_model.c
|
||||
@@ -39,6 +39,8 @@
|
||||
static cvar_t external_ents = {"external_ents", "1", CVAR_ARCHIVE};
|
||||
static cvar_t external_vis = {"external_vis", "1", CVAR_ARCHIVE};
|
||||
|
||||
+extern cvar_t r_externaltexture_fix; //mk
|
||||
+
|
||||
static byte *mod_novis;
|
||||
static int mod_novis_capacity;
|
||||
|
||||
@@ -549,6 +551,13 @@ static void Mod_LoadTextures (lump_t *l)
|
||||
{
|
||||
if (!q_strncasecmp(tx->name,"sky",3)) //sky texture //also note -- was Q_strncmp, changed to match qbsp
|
||||
{
|
||||
+ if (r_externaltexture_fix.value) { //mk
|
||||
+ if (strstr(tx->name,"sky4")) {
|
||||
+ if (CRC_Block((byte *)(tx+1), tx->width * tx->height)==13039)
|
||||
+ q_strlcpy(tx->name, "sky1", sizeof(tx->name));
|
||||
+ Con_Printf(" using %s\n", tx->name);
|
||||
+ }
|
||||
+ }
|
||||
if (loadmodel->bspversion == BSPVERSION_QUAKE64)
|
||||
Sky_LoadTextureQ64 (loadmodel, tx);
|
||||
else
|
||||
@@ -606,6 +615,50 @@ static void Mod_LoadTextures (lump_t *l)
|
||||
//external textures -- first look in "textures/mapname/" then look in "textures/"
|
||||
mark = Hunk_LowMark ();
|
||||
COM_StripExtension (loadmodel->name + 5, mapname, sizeof(mapname));
|
||||
+
|
||||
+ if (r_externaltexture_fix.value) { //mk
|
||||
+ if (strstr(tx->name,"plat_top1")) {
|
||||
+ if (CRC_Block((byte *)(tx+1), tx->width * tx->height)==24428)
|
||||
+ q_strlcpy(tx->name, "plat_top1_cable", sizeof(tx->name));
|
||||
+ else
|
||||
+ q_strlcpy(tx->name, "plat_top1_bolt", sizeof(tx->name));
|
||||
+ Con_Printf(" using %s\n", tx->name);
|
||||
+ }
|
||||
+ if (strstr(tx->name,"metal5_2")) {
|
||||
+ if (CRC_Block((byte *)(tx+1), tx->width * tx->height)==49173)
|
||||
+ q_strlcpy(tx->name, "metal5_2_x", sizeof(tx->name));
|
||||
+ else
|
||||
+ q_strlcpy(tx->name, "metal5_2_arc", sizeof(tx->name));
|
||||
+ Con_Printf(" using %s\n", tx->name);
|
||||
+ }
|
||||
+ if (strstr(tx->name,"metal5_4")) {
|
||||
+ if (CRC_Block((byte *)(tx+1), tx->width * tx->height)==20977)
|
||||
+ q_strlcpy(tx->name, "metal5_4_double", sizeof(tx->name));
|
||||
+ else
|
||||
+ q_strlcpy(tx->name, "metal5_4_arc", sizeof(tx->name));
|
||||
+ Con_Printf(" using %s\n", tx->name);
|
||||
+ }
|
||||
+ if (strstr(tx->name,"metal5_8")) {
|
||||
+ if (CRC_Block((byte *)(tx+1), tx->width * tx->height)==48444)
|
||||
+ q_strlcpy(tx->name, "metal5_8_rune", sizeof(tx->name));
|
||||
+ else
|
||||
+ q_strlcpy(tx->name, "metal5_8_back", sizeof(tx->name));
|
||||
+ Con_Printf(" using %s\n", tx->name);
|
||||
+ }
|
||||
+ if (strstr(tx->name,"metal5_8")) {
|
||||
+ if (CRC_Block((byte *)(tx+1), tx->width * tx->height)==48444)
|
||||
+ q_strlcpy(tx->name, "metal5_8_rune", sizeof(tx->name));
|
||||
+ else
|
||||
+ q_strlcpy(tx->name, "metal5_8_back", sizeof(tx->name));
|
||||
+ Con_Printf(" using %s\n", tx->name);
|
||||
+ }
|
||||
+ if (strstr(tx->name,"window03")) {
|
||||
+ if (CRC_Block((byte *)(tx+1), tx->width * tx->height)==63697) // e4m2 variant
|
||||
+ q_strlcpy(tx->name, "window03_e4m2", sizeof(tx->name));
|
||||
+ Con_Printf(" using %s\n", tx->name);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
q_snprintf (filename, sizeof(filename), "textures/%s/%s", mapname, tx->name);
|
||||
data = Image_LoadImage (filename, &fwidth, &fheight);
|
||||
if (!data)
|
||||
diff --git a/Quake/gl_rmain.c b/Quake/gl_rmain.c
|
||||
index 6883161..4a8a745 100644
|
||||
--- a/Quake/gl_rmain.c
|
||||
+++ b/Quake/gl_rmain.c
|
||||
@@ -100,6 +100,8 @@
|
||||
extern cvar_t r_vfog;
|
||||
//johnfitz
|
||||
|
||||
+cvar_t r_externaltexture_fix = {"r_externaltexture_fix", "0", CVAR_ARCHIVE}; //mk
|
||||
+
|
||||
cvar_t gl_zfix = {"gl_zfix", "0", CVAR_NONE}; // QuakeSpasm z-fighting fix
|
||||
|
||||
cvar_t r_lavaalpha = {"r_lavaalpha","0",CVAR_NONE};
|
||||
diff --git a/Quake/gl_rmisc.c b/Quake/gl_rmisc.c
|
||||
index 963d55e..e9b251b 100644
|
||||
--- a/Quake/gl_rmisc.c
|
||||
+++ b/Quake/gl_rmisc.c
|
||||
@@ -47,6 +47,7 @@
|
||||
extern cvar_t r_noshadow_list;
|
||||
//johnfitz
|
||||
extern cvar_t gl_zfix; // QuakeSpasm z-fighting fix
|
||||
+extern cvar_t r_externaltexture_fix; //mk
|
||||
|
||||
extern gltexture_t *playertextures[MAX_SCOREBOARD]; //johnfitz
|
||||
|
||||
@@ -230,6 +231,7 @@ void R_Init (void)
|
||||
Cvar_SetCallback (&r_lavaalpha, R_SetLavaalpha_f);
|
||||
Cvar_SetCallback (&r_telealpha, R_SetTelealpha_f);
|
||||
Cvar_SetCallback (&r_slimealpha, R_SetSlimealpha_f);
|
||||
+ Cvar_RegisterVariable (&r_externaltexture_fix);//mk
|
||||
|
||||
R_InitParticles ();
|
||||
R_SetClearColor_f (&r_clearcolor); //johnfitz
|
||||
@@ -0,0 +1,34 @@
|
||||
allow plain files to override files inside a PAK -- Sander van Dijk.
|
||||
|
||||
diff --git a/Quake/common.c b/Quake/common.c
|
||||
index c80450f..6074711 100644
|
||||
--- a/Quake/common.c
|
||||
+++ b/Quake/common.c
|
||||
@@ -2107,13 +2107,6 @@ static void COM_AddGameDirectory (const char *base, const char *dir)
|
||||
else path_id = 1U;
|
||||
|
||||
_add_path:
|
||||
- // add the directory to the search path
|
||||
- search = (searchpath_t *) Z_Malloc(sizeof(searchpath_t));
|
||||
- search->path_id = path_id;
|
||||
- q_strlcpy (search->filename, com_gamedir, sizeof(search->filename));
|
||||
- search->next = com_searchpaths;
|
||||
- com_searchpaths = search;
|
||||
-
|
||||
// add any pak files in the format pak0.pak pak1.pak, ...
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
@@ -2145,6 +2138,13 @@ _add_path:
|
||||
if (!pak) break;
|
||||
}
|
||||
|
||||
+ // add the directory to the search path -- moved here from before the pakX.pak loop -- svdijk.
|
||||
+ search = (searchpath_t *) Z_Malloc(sizeof(searchpath_t));
|
||||
+ search->path_id = path_id;
|
||||
+ q_strlcpy (search->filename, com_gamedir, sizeof(search->filename));
|
||||
+ search->next = com_searchpaths;
|
||||
+ com_searchpaths = search;
|
||||
+
|
||||
if (!been_here && host_parms->userdir != host_parms->basedir)
|
||||
{
|
||||
been_here = true;
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
gcc -Wall mk_header.c -o mk_header
|
||||
|
||||
dumps the bytes of given input to a C header as
|
||||
comma separated hexadecimal values. the output
|
||||
header can be used in a C source like:
|
||||
|
||||
const char bin[] =
|
||||
{
|
||||
# include "output.h"
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
struct stat s;
|
||||
unsigned char *buf, *ptr;
|
||||
const char *output;
|
||||
long i, j;
|
||||
|
||||
if (argc != 2 && argc != 3)
|
||||
{
|
||||
printf ("Usage: mk_header <input> [output]\n"
|
||||
"Default output file is \"output.h\"\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (stat(argv[1], &s) == -1 ||
|
||||
! S_ISREG(s.st_mode) )
|
||||
{
|
||||
printf ("Couldn't stat %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (s.st_size == 0)
|
||||
{
|
||||
printf ("%s is an empty file\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
buf = (unsigned char *) malloc (s.st_size);
|
||||
if (buf == NULL)
|
||||
{
|
||||
printf ("Couldn't malloc %ld bytes\n",
|
||||
(long)s.st_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
f = fopen (argv[1], "rb");
|
||||
if (f == NULL)
|
||||
{
|
||||
free(buf);
|
||||
printf ("Couldn't open %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fread (buf, 1, s.st_size, f) != (size_t) s.st_size)
|
||||
{
|
||||
fclose (f);
|
||||
free (buf);
|
||||
printf ("Error reading %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
fclose (f);
|
||||
|
||||
output = (argc == 3) ? argv[2] : "output.h";
|
||||
f = fopen (output, "wb");
|
||||
if (!f)
|
||||
{
|
||||
free (buf);
|
||||
printf ("Couldn't open %s\n", output);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0, ptr = buf; i < s.st_size; ++i)
|
||||
{
|
||||
fprintf (f, "0x%02x", *ptr++);
|
||||
if (i == s.st_size - 1)
|
||||
break;
|
||||
fprintf (f, ",");
|
||||
if (++j < 16)
|
||||
fprintf (f, " ");
|
||||
else
|
||||
{
|
||||
j = 0;
|
||||
fprintf (f, "\n");
|
||||
}
|
||||
}
|
||||
fprintf (f, "\n");
|
||||
|
||||
fclose (f);
|
||||
free (buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
INPUT := gfx/conback.lmp \
|
||||
maps/[email protected] \
|
||||
maps/[email protected] \
|
||||
maps/[email protected] \
|
||||
maps/[email protected] \
|
||||
maps/[email protected] \
|
||||
maps/[email protected] \
|
||||
default.cfg
|
||||
|
||||
OUTPUT := quakespasm.pak
|
||||
|
||||
$(OUTPUT): $(INPUT)
|
||||
./mkpak.sh $(INPUT) > $(OUTPUT)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(OUTPUT)
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// load keybindings
|
||||
//
|
||||
// commands with a leading + will also be called for key up events with
|
||||
// the + changed to a -
|
||||
unbindall
|
||||
|
||||
//
|
||||
// character controls
|
||||
//
|
||||
|
||||
bind ALT +strafe
|
||||
|
||||
bind , +moveleft
|
||||
bind a +moveleft
|
||||
bind . +moveright
|
||||
bind d +moveright
|
||||
bind DEL +lookdown
|
||||
bind PGDN +lookup
|
||||
bind END centerview
|
||||
|
||||
bind e +moveup
|
||||
bind c +movedown
|
||||
bind SHIFT +speed
|
||||
bind CTRL +attack
|
||||
bind UPARROW +forward
|
||||
bind w +forward
|
||||
bind DOWNARROW +back
|
||||
bind s +back
|
||||
bind LEFTARROW +left
|
||||
bind RIGHTARROW +right
|
||||
|
||||
bind SPACE +jump
|
||||
//bind ENTER +jump
|
||||
|
||||
bind TAB +showscores
|
||||
|
||||
bind 1 "impulse 1"
|
||||
bind 2 "impulse 2"
|
||||
bind 3 "impulse 3"
|
||||
bind 4 "impulse 4"
|
||||
bind 5 "impulse 5"
|
||||
bind 6 "impulse 6"
|
||||
bind 7 "impulse 7"
|
||||
bind 8 "impulse 8"
|
||||
|
||||
bind 0 "impulse 0"
|
||||
|
||||
bind / "impulse 10" // change weapon
|
||||
bind MWHEELDOWN "impulse 10"
|
||||
bind MWHEELUP "impulse 12"
|
||||
|
||||
// zoom
|
||||
alias zoom_in "sensitivity 2;fov 90;wait;fov 70;wait;fov 50;wait;fov 30;wait;fov 10;wait;fov 5;bind F11 zoom_out"
|
||||
alias zoom_out "sensitivity 4;fov 5;wait;fov 10;wait;fov 30;wait;fov 50;wait;fov 70;wait;fov 90;bind F11 zoom_in; sensitivity 3"
|
||||
bind F11 zoom_in
|
||||
|
||||
// Function keys
|
||||
bind F1 "help"
|
||||
bind F2 "menu_save"
|
||||
bind F3 "menu_load"
|
||||
bind F4 "menu_options"
|
||||
bind F5 "menu_multiplayer"
|
||||
bind F6 "echo Quicksaving...; wait; save quick"
|
||||
bind F9 "echo Quickloading...; wait; load quick"
|
||||
bind F10 "quit"
|
||||
bind F12 "screenshot"
|
||||
|
||||
// mouse options
|
||||
bind \ +mlook
|
||||
|
||||
//
|
||||
// client environment commands
|
||||
//
|
||||
bind PAUSE "pause"
|
||||
bind ESCAPE "togglemenu"
|
||||
bind ~ "toggleconsole"
|
||||
bind ` "toggleconsole"
|
||||
|
||||
bind t "messagemode"
|
||||
|
||||
bind + "sizeup"
|
||||
bind = "sizeup"
|
||||
bind - "sizedown"
|
||||
|
||||
bind INS +klook
|
||||
|
||||
//
|
||||
// mouse buttons
|
||||
//
|
||||
bind MOUSE1 +attack
|
||||
//bind MOUSE2 +forward
|
||||
bind MOUSE2 +jump
|
||||
//bind MOUSE3 +mlook
|
||||
|
||||
//
|
||||
// game controller
|
||||
//
|
||||
bind LSHOULDER "impulse 12"
|
||||
bind RSHOULDER "impulse 10"
|
||||
bind LTRIGGER +jump
|
||||
bind RTRIGGER +attack
|
||||
|
||||
//
|
||||
// default cvars
|
||||
//
|
||||
gamma 1.0
|
||||
volume 0.7
|
||||
sensitivity 3
|
||||
|
||||
//viewsize 100
|
||||
viewsize 110
|
||||
scr_conscale 1.6
|
||||
scr_menuscale 1.6
|
||||
scr_sbarscale 1.6
|
||||
|
||||
// default to mouse-look enabled
|
||||
+mlook
|
||||
@@ -0,0 +1,76 @@
|
||||
--- default.cfg~
|
||||
+++ default.cfg
|
||||
@@ -12,24 +12,26 @@
|
||||
bind ALT +strafe
|
||||
|
||||
bind , +moveleft
|
||||
+bind a +moveleft
|
||||
bind . +moveright
|
||||
+bind d +moveright
|
||||
bind DEL +lookdown
|
||||
bind PGDN +lookup
|
||||
bind END centerview
|
||||
-bind z +lookdown
|
||||
-bind a +lookup
|
||||
|
||||
-bind d +moveup
|
||||
+bind e +moveup
|
||||
bind c +movedown
|
||||
bind SHIFT +speed
|
||||
bind CTRL +attack
|
||||
bind UPARROW +forward
|
||||
+bind w +forward
|
||||
bind DOWNARROW +back
|
||||
+bind s +back
|
||||
bind LEFTARROW +left
|
||||
bind RIGHTARROW +right
|
||||
|
||||
bind SPACE +jump
|
||||
-bind ENTER +jump
|
||||
+//bind ENTER +jump
|
||||
|
||||
bind TAB +showscores
|
||||
|
||||
@@ -45,6 +47,8 @@
|
||||
bind 0 "impulse 0"
|
||||
|
||||
bind / "impulse 10" // change weapon
|
||||
+bind MWHEELDOWN "impulse 10"
|
||||
+bind MWHEELUP "impulse 12"
|
||||
|
||||
// zoom
|
||||
alias zoom_in "sensitivity 2;fov 90;wait;fov 70;wait;fov 50;wait;fov 30;wait;fov 10;wait;fov 5;bind F11 zoom_out"
|
||||
@@ -85,14 +89,30 @@
|
||||
// mouse buttons
|
||||
//
|
||||
bind MOUSE1 +attack
|
||||
-bind MOUSE2 +forward
|
||||
-bind MOUSE3 +mlook
|
||||
+//bind MOUSE2 +forward
|
||||
+bind MOUSE2 +jump
|
||||
+//bind MOUSE3 +mlook
|
||||
+
|
||||
+//
|
||||
+// game controller
|
||||
+//
|
||||
+bind LSHOULDER "impulse 12"
|
||||
+bind RSHOULDER "impulse 10"
|
||||
+bind LTRIGGER +jump
|
||||
+bind RTRIGGER +attack
|
||||
|
||||
//
|
||||
// default cvars
|
||||
//
|
||||
-viewsize 100
|
||||
gamma 1.0
|
||||
volume 0.7
|
||||
sensitivity 3
|
||||
|
||||
+//viewsize 100
|
||||
+viewsize 110
|
||||
+scr_conscale 1.6
|
||||
+scr_menuscale 1.6
|
||||
+scr_sbarscale 1.6
|
||||
+
|
||||
+// default to mouse-look enabled
|
||||
++mlook
|
||||
Binary file not shown.
@@ -0,0 +1,18 @@
|
||||
--- e1m1.ent
|
||||
+++ [email protected]
|
||||
@@ -715,14 +715,15 @@
|
||||
{
|
||||
"classname" "func_door"
|
||||
"targetname" "t4"
|
||||
"angle" "-2"
|
||||
"spawnflags" "1"
|
||||
"sounds" "2"
|
||||
"model" "*15"
|
||||
+"lip" "7" // svdijk -- added to prevent z-fighting
|
||||
}
|
||||
{
|
||||
"classname" "trigger_multiple"
|
||||
"target" "t4"
|
||||
"health" "1"
|
||||
"model" "*16"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
--- e1m2.ent
|
||||
+++ [email protected]
|
||||
@@ -1567,23 +1567,23 @@
|
||||
{
|
||||
"light" "200"
|
||||
"origin" "-612 -500 548"
|
||||
"classname" "light"
|
||||
}
|
||||
{
|
||||
"classname" "func_door"
|
||||
-"angle" "90"
|
||||
+"angle" "91" // svdijk -- changed to prevent z-fighting (was "90")
|
||||
"targetname" "t110"
|
||||
"wait" "-1"
|
||||
"model" "*33"
|
||||
}
|
||||
{
|
||||
"sounds" "3"
|
||||
"classname" "func_door"
|
||||
-"angle" "270"
|
||||
+"angle" "269" // svdijk -- changed to prevent z-fighting (was "270")
|
||||
"wait" "-1"
|
||||
"model" "*34"
|
||||
}
|
||||
{
|
||||
"classname" "trigger_once"
|
||||
"target" "t110"
|
||||
"model" "*35"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
--- e1m4.ent
|
||||
+++ [email protected]
|
||||
@@ -2143,12 +2143,13 @@
|
||||
{
|
||||
"classname" "func_door_secret"
|
||||
"angle" "0"
|
||||
"spawnflags" "1"
|
||||
"targetname" "t91"
|
||||
"model" "*53"
|
||||
+"t_length" "73" // svdijk -- added to prevent z-fighting
|
||||
}
|
||||
{
|
||||
"classname" "func_button"
|
||||
"angle" "-2"
|
||||
"wait" "-1"
|
||||
"target" "t92"
|
||||
@@ -2202,12 +2203,13 @@
|
||||
{
|
||||
"spawnflags" "3"
|
||||
"angle" "0"
|
||||
"classname" "func_door_secret"
|
||||
"targetname" "t91"
|
||||
"model" "*60"
|
||||
+"t_length" "73" // svdijk -- added to prevent z-fighting
|
||||
}
|
||||
{
|
||||
"light" "150"
|
||||
"origin" "680 -256 1144"
|
||||
"classname" "light"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
--- e2m2.ent
|
||||
+++ [email protected]
|
||||
@@ -908,20 +908,21 @@
|
||||
{
|
||||
"classname" "func_door"
|
||||
"angle" "-2"
|
||||
"spawnflags" "33"
|
||||
"speed" "10"
|
||||
"sounds" "3"
|
||||
"wait" "-1"
|
||||
"targetname" "t16"
|
||||
"dmg" "100"
|
||||
"model" "*13"
|
||||
+"lip" "7" // svdijk -- added to prevent z-fighting
|
||||
}
|
||||
{
|
||||
"sounds" "3"
|
||||
"classname" "func_door"
|
||||
"angle" "90"
|
||||
"spawnflags" "2056"
|
||||
"wait" "-1"
|
||||
"model" "*14"
|
||||
}
|
||||
{
|
||||
@@ -1423,27 +1424,27 @@
|
||||
{
|
||||
"target" "t39"
|
||||
"targetname" "t40"
|
||||
"origin" "-216 280 104"
|
||||
"classname" "path_corner"
|
||||
}
|
||||
{
|
||||
"target" "t40"
|
||||
"targetname" "t38"
|
||||
"classname" "path_corner"
|
||||
-"origin" "-16 280 104"
|
||||
+"origin" "-15 280 104" // svdijk -- changed to prevent z-fighting (was "-16 280 104")
|
||||
}
|
||||
{
|
||||
"target" "t38"
|
||||
"wait" "-1"
|
||||
"targetname" "t39"
|
||||
-"origin" "-16 280 104"
|
||||
+"origin" "-15 280 104" // svdijk -- changed to prevent z-fighting (was "-16 280 104")
|
||||
"classname" "path_corner"
|
||||
}
|
||||
{
|
||||
"angle" "180"
|
||||
"origin" "680 1472 24"
|
||||
"classname" "monster_ogre"
|
||||
"spawnflags" "256"
|
||||
}
|
||||
{
|
||||
"spawnflags" "256"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,74 @@
|
||||
--- e2m3.ent
|
||||
+++ [email protected]
|
||||
@@ -1226,21 +1226,23 @@
|
||||
{
|
||||
"classname" "func_door"
|
||||
"angle" "-2"
|
||||
"spawnflags" "1"
|
||||
"targetname" "t11"
|
||||
"wait" "10"
|
||||
"model" "*25"
|
||||
+"lip" "7" // svdijk -- added to prevent z-fighting
|
||||
}
|
||||
{
|
||||
"classname" "func_door_secret"
|
||||
"angle" "90"
|
||||
"spawnflags" "8"
|
||||
"targetname" "t11"
|
||||
"model" "*26"
|
||||
+"t_length" "65" // svdijk -- added to prevent z-fighting
|
||||
}
|
||||
{
|
||||
"classname" "light"
|
||||
"origin" "1248 -288 312"
|
||||
"light" "150"
|
||||
}
|
||||
{
|
||||
@@ -1907,14 +1909,15 @@
|
||||
}
|
||||
{
|
||||
"classname" "func_door_secret"
|
||||
"spawnflags" "2051"
|
||||
"targetname" "t36"
|
||||
"angle" "90"
|
||||
"model" "*37"
|
||||
+"t_length" "65" // svdijk -- added to prevent z-fighting
|
||||
}
|
||||
{
|
||||
"classname" "light"
|
||||
"origin" "-1288 640 -80"
|
||||
"light" "160"
|
||||
}
|
||||
{
|
||||
@@ -1939,14 +1942,15 @@
|
||||
}
|
||||
{
|
||||
"classname" "func_door_secret"
|
||||
"targetname" "t36"
|
||||
"angle" "270"
|
||||
"spawnflags" "2049"
|
||||
"model" "*38"
|
||||
+"t_length" "65" // svdijk -- added to prevent z-fighting
|
||||
}
|
||||
{
|
||||
"classname" "item_armor2"
|
||||
"origin" "1128 600 -176"
|
||||
"spawnflags" "1024"
|
||||
}
|
||||
{
|
||||
@@ -2643,14 +2647,15 @@
|
||||
}
|
||||
{
|
||||
"classname" "func_door_secret"
|
||||
"angle" "180"
|
||||
"spawnflags" "2"
|
||||
"targetname" "t41"
|
||||
"model" "*66"
|
||||
+"t_length" "65" // svdijk -- added to prevent z-fighting
|
||||
}
|
||||
{
|
||||
"classname" "trigger_multiple"
|
||||
"target" "t41"
|
||||
"model" "*67"
|
||||
}
|
||||
{
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
--- e2m7.ent
|
||||
+++ [email protected]
|
||||
@@ -1449,18 +1449,19 @@
|
||||
{
|
||||
"targetname" "t119"
|
||||
"classname" "func_door"
|
||||
"wait" "-1"
|
||||
"angle" "-1"
|
||||
"speed" "30"
|
||||
"message" "Go for a swim first..."
|
||||
"sounds" "3"
|
||||
"model" "*40"
|
||||
+"origin" "-1 0 0" // svdijk -- added to prevent z-fighting
|
||||
}
|
||||
{
|
||||
"classname" "func_button"
|
||||
"angle" "0"
|
||||
"wait" "-1"
|
||||
"target" "t45"
|
||||
"model" "*41"
|
||||
}
|
||||
{
|
||||
File diff suppressed because it is too large
Load Diff
Executable
+135
@@ -0,0 +1,135 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2014, Sander van Dijk <[email protected]>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
error() {
|
||||
echo "$(basename "$0"): $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
assert_valid_stdout() {
|
||||
if test -t 1
|
||||
then
|
||||
error "Usage: $(basename "$0") [file ...] > output.pak"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_valid_file() {
|
||||
if test ! -e "$1"
|
||||
then
|
||||
error "$1: No such file"
|
||||
fi
|
||||
if test ! -f "$1"
|
||||
then
|
||||
error "$f: Not a regular file"
|
||||
fi
|
||||
if test ! -r "$1"
|
||||
then
|
||||
error "$1: Permission denied"
|
||||
fi
|
||||
if test $(echo -n "$1" | wc -c) -gt 55
|
||||
then
|
||||
error "$1: Name too long"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_valid_int32() {
|
||||
if test $1 -lt -2147483648 -o $1 -gt 2147483647
|
||||
then
|
||||
error "Too much data"
|
||||
fi
|
||||
}
|
||||
|
||||
octal() {
|
||||
if test $1 -gt 7
|
||||
then
|
||||
octal $(expr $1 / 8)
|
||||
fi
|
||||
echo -n $(expr $1 % 8)
|
||||
}
|
||||
|
||||
byte() {
|
||||
echo -en \\0$(octal $1)
|
||||
}
|
||||
|
||||
little_endian_uint32() {
|
||||
byte $(expr $1 % 256)
|
||||
byte $(expr $1 / 256 % 256)
|
||||
byte $(expr $1 / 65536 % 256)
|
||||
byte $(expr $1 / 16777216 % 256)
|
||||
}
|
||||
|
||||
little_endian_int32() {
|
||||
if test $1 -lt 0
|
||||
then
|
||||
little_endian_uint32 $(expr $1 + 4294967296)
|
||||
else
|
||||
little_endian_uint32 $1
|
||||
fi
|
||||
}
|
||||
|
||||
zero_padding() {
|
||||
if test $1 -lt 1
|
||||
then
|
||||
return
|
||||
fi
|
||||
byte 0
|
||||
zero_padding $(expr $1 - 1)
|
||||
}
|
||||
|
||||
header() {
|
||||
echo -n PACK
|
||||
little_endian_int32 $1
|
||||
little_endian_int32 $2
|
||||
}
|
||||
|
||||
directory_entry() {
|
||||
echo -n "$1"
|
||||
zero_padding $(expr 56 - $(echo -n "$1" | wc -c))
|
||||
little_endian_int32 $2
|
||||
little_endian_int32 $3
|
||||
}
|
||||
|
||||
assert_valid_stdout
|
||||
|
||||
directory_offset=12
|
||||
directory_size=0
|
||||
for file in "$@"
|
||||
do
|
||||
assert_valid_file "$file"
|
||||
file_offset=$directory_offset
|
||||
assert_valid_int32 $file_offset
|
||||
file_size=$(wc -c < "$file")
|
||||
assert_valid_int32 $file_size
|
||||
directory_offset=$(expr $directory_offset + $file_size)
|
||||
assert_valid_int32 $directory_offset
|
||||
directory_size=$(expr $directory_size + 64)
|
||||
assert_valid_int32 $directory_size
|
||||
done
|
||||
|
||||
header $directory_offset $directory_size
|
||||
|
||||
for file in "$@"
|
||||
do
|
||||
cat "$file"
|
||||
done
|
||||
|
||||
file_offset=12
|
||||
for file in "$@"
|
||||
do
|
||||
file_size=$(wc -c < "$file")
|
||||
directory_entry "$file" $file_offset $file_size
|
||||
file_offset=$(expr $file_offset + $file_size)
|
||||
done
|
||||
+256
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* stupid test tool that reports the type sizes and
|
||||
* their alignment offsets in structures, and the byte
|
||||
* order as detected at runtime and compile time.
|
||||
*/
|
||||
|
||||
/*
|
||||
* endianness stuff: <sys/types.h> is supposed
|
||||
* to succeed in locating the correct endian.h
|
||||
* this BSD style may not work everywhere.
|
||||
*/
|
||||
|
||||
#undef ENDIAN_GUESSED_SAFE
|
||||
#undef ENDIAN_ASSUMED_UNSAFE
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* include more if it didn't work: */
|
||||
#if !defined(BYTE_ORDER)
|
||||
|
||||
# if defined(__linux__) || defined(__linux)
|
||||
# include <endian.h>
|
||||
# elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
# include <machine/endian.h>
|
||||
# elif defined(__sun) || defined(__svr4__)
|
||||
# include <sys/byteorder.h>
|
||||
# elif defined(_AIX)
|
||||
# include <sys/machine.h>
|
||||
# elif defined(sgi)
|
||||
# include <sys/endian.h>
|
||||
# elif defined(__DJGPP__)
|
||||
# include <machine/endian.h>
|
||||
# endif
|
||||
|
||||
#endif /* endian includes */
|
||||
|
||||
|
||||
#if defined(__BYTE_ORDER) && !defined(BYTE_ORDER)
|
||||
#define BYTE_ORDER __BYTE_ORDER
|
||||
#endif /* __BYTE_ORDER */
|
||||
|
||||
#if !defined(PDP_ENDIAN)
|
||||
#if defined(__PDP_ENDIAN)
|
||||
#define PDP_ENDIAN __PDP_ENDIAN
|
||||
#else
|
||||
#define PDP_ENDIAN 3412
|
||||
#endif
|
||||
#endif /* NUXI endian (not supported) */
|
||||
|
||||
#if defined(__LITTLE_ENDIAN) && !defined(LITTLE_ENDIAN)
|
||||
#define LITTLE_ENDIAN __LITTLE_ENDIAN
|
||||
#endif /* __LITTLE_ENDIAN */
|
||||
|
||||
#if defined(__BIG_ENDIAN) && !defined(BIG_ENDIAN)
|
||||
#define BIG_ENDIAN __BIG_ENDIAN
|
||||
#endif /* __LITTLE_ENDIAN */
|
||||
|
||||
|
||||
#if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
|
||||
|
||||
# if (BYTE_ORDER != LITTLE_ENDIAN) && (BYTE_ORDER != BIG_ENDIAN)
|
||||
# error "Unsupported endianness."
|
||||
# endif
|
||||
|
||||
#else /* one of the definitions is mising. */
|
||||
|
||||
# undef BYTE_ORDER
|
||||
# undef LITTLE_ENDIAN
|
||||
# undef BIG_ENDIAN
|
||||
# undef PDP_ENDIAN
|
||||
# define LITTLE_ENDIAN 1234
|
||||
# define BIG_ENDIAN 4321
|
||||
# define PDP_ENDIAN 3412
|
||||
|
||||
#endif /* byte order defs */
|
||||
|
||||
|
||||
#if !defined(BYTE_ORDER)
|
||||
/* supposedly safe assumptions: these may actually
|
||||
* be OS dependant and listing all possible compiler
|
||||
* macros here is impossible (the ones here are gcc
|
||||
* flags, mostly.) so, proceed carefully..
|
||||
*/
|
||||
|
||||
# if defined(__DJGPP__) || defined(MSDOS) || defined(__MSDOS__)
|
||||
# define BYTE_ORDER LITTLE_ENDIAN /* DOS */
|
||||
|
||||
# elif defined(__sun) || defined(__svr4__) /* solaris */
|
||||
# if defined(_LITTLE_ENDIAN) /* x86 */
|
||||
# define BYTE_ORDER LITTLE_ENDIAN
|
||||
# elif defined(_BIG_ENDIAN) /* sparc */
|
||||
# define BYTE_ORDER BIG_ENDIAN
|
||||
# endif
|
||||
|
||||
# elif defined(__i386) || defined(__i386__) || defined(__386__) || defined(_M_IX86)
|
||||
# define BYTE_ORDER LITTLE_ENDIAN /* any x86 */
|
||||
|
||||
# elif defined(__amd64) || defined(__x86_64__) || defined(_M_X64)
|
||||
# define BYTE_ORDER LITTLE_ENDIAN /* any x64 */
|
||||
|
||||
# elif defined(_M_IA64)
|
||||
# define BYTE_ORDER LITTLE_ENDIAN /* ia64 / Visual C */
|
||||
|
||||
# elif defined (__ppc__) || defined(__POWERPC__) || defined(_M_PPC)
|
||||
# define BYTE_ORDER BIG_ENDIAN /* PPC: big endian */
|
||||
|
||||
# elif (defined(__alpha__) || defined(__alpha)) || defined(_M_ALPHA)
|
||||
# define BYTE_ORDER LITTLE_ENDIAN /* should be safe */
|
||||
|
||||
# elif defined(_WIN32) || defined(_WIN64) /* windows : */
|
||||
# define BYTE_ORDER LITTLE_ENDIAN /* should be safe */
|
||||
|
||||
# elif defined(__hppa) || defined(__hppa__) || defined(__sparc) || defined(__sparc__) /* others: check! */
|
||||
# define BYTE_ORDER BIG_ENDIAN
|
||||
|
||||
# endif
|
||||
|
||||
# if defined(BYTE_ORDER)
|
||||
/* raise a flag, just in case: */
|
||||
# define ENDIAN_GUESSED_SAFE BYTE_ORDER
|
||||
# endif
|
||||
|
||||
#endif /* supposedly safe assumptions */
|
||||
|
||||
|
||||
#if !defined(BYTE_ORDER)
|
||||
|
||||
/* brain-dead fallback: default to little endian.
|
||||
* change if necessary!!!!
|
||||
*/
|
||||
# define BYTE_ORDER LITTLE_ENDIAN
|
||||
# define ENDIAN_ASSUMED_UNSAFE BYTE_ORDER
|
||||
|
||||
#endif /* fallback. */
|
||||
|
||||
#if defined(ENDIAN_ASSUMED_UNSAFE)
|
||||
/*
|
||||
# if (ENDIAN_ASSUMED_UNSAFE == LITTLE_ENDIAN)
|
||||
# warning "Cannot determine endianess. Using LIL endian as an UNSAFE default"
|
||||
# elif (ENDIAN_ASSUMED_UNSAFE == PDP_ENDIAN)
|
||||
# warning "Cannot determine endianess. Using PDP (NUXI) as an UNSAFE default."
|
||||
# elif (ENDIAN_ASSUMED_UNSAFE == BIG_ENDIAN)
|
||||
# warning "Cannot determine endianess. Using BIG endian as an UNSAFE default."
|
||||
# endif
|
||||
*/
|
||||
#endif /* ENDIAN_ASSUMED_UNSAFE */
|
||||
|
||||
#define COMPILED_BYTEORDER BYTE_ORDER
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int DetectByteorder (void)
|
||||
{
|
||||
int i = 0x12345678;
|
||||
/* U N I X */
|
||||
|
||||
/*
|
||||
BE_ORDER: 12 34 56 78
|
||||
U N I X
|
||||
|
||||
LE_ORDER: 78 56 34 12
|
||||
X I N U
|
||||
|
||||
PDP_ORDER: 34 12 78 56
|
||||
N U X I
|
||||
*/
|
||||
|
||||
if ( *(char *)&i == 0x12 )
|
||||
return BIG_ENDIAN;
|
||||
else if ( *(char *)&i == 0x78 )
|
||||
return LITTLE_ENDIAN;
|
||||
else if ( *(char *)&i == 0x34 )
|
||||
return PDP_ENDIAN;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct align_test_char { char dummy; char test; };
|
||||
struct align_test_short { char dummy; short test; };
|
||||
struct align_test_int { char dummy; int test; };
|
||||
struct align_test_long { char dummy; long test; };
|
||||
struct align_test_longlong { char dummy; long long test; };
|
||||
struct align_test_float { char dummy; float test; };
|
||||
struct align_test_double { char dummy; double test; };
|
||||
struct align_test_longdouble { char dummy; long double test;};
|
||||
struct align_test_voidptr { char dummy; void *test; };
|
||||
|
||||
int main (void)
|
||||
{
|
||||
int tmp = ((char) -1);
|
||||
|
||||
printf ("char is signed type : %s - char is %s\n", (tmp < 0) ? "yes" : "no", (tmp < 0) ? "SIGNED" : "UNSIGNED");
|
||||
printf ("Type sizes and alignment within structures:\n");
|
||||
printf ("char : %d, packing offset: %d\n", (int) sizeof(char), (int) ((size_t) &((struct align_test_char *)0)->test));
|
||||
printf ("short : %d, packing offset: %d\n", (int) sizeof(short), (int) ((size_t) &((struct align_test_short *)0)->test));
|
||||
printf ("int : %d, packing offset: %d\n", (int) sizeof(int), (int) ((size_t) &((struct align_test_int *)0)->test));
|
||||
printf ("long : %d, packing offset: %d\n", (int) sizeof(long), (int) ((size_t) &((struct align_test_long *)0)->test));
|
||||
printf ("long long : %d, packing offset: %d\n", (int) sizeof(long long),(int) ((size_t) &((struct align_test_longlong *)0)->test));
|
||||
printf ("void *ptr : %d, packing offset: %d\n", (int) sizeof(void *), (int) ((size_t) &((struct align_test_voidptr *)0)->test));
|
||||
printf ("float : %d, packing offset: %d\n", (int) sizeof(float), (int) ((size_t) &((struct align_test_float *)0)->test));
|
||||
printf ("double : %d, packing offset: %d\n", (int) sizeof(double), (int) ((size_t) &((struct align_test_double *)0)->test));
|
||||
printf ("long double: %d, packing offset: %d\n", (int) sizeof(long double),(int)((size_t)&((struct align_test_longdouble *)0)->test));
|
||||
|
||||
printf ("ENDIANNESS (BYTE ORDER):\n");
|
||||
|
||||
tmp = DetectByteorder();
|
||||
printf ("Runtime detection : ");
|
||||
switch (tmp)
|
||||
{
|
||||
case BIG_ENDIAN:
|
||||
printf ("Big Endian");
|
||||
break;
|
||||
case LITTLE_ENDIAN:
|
||||
printf ("Little Endian");
|
||||
break;
|
||||
case PDP_ENDIAN:
|
||||
printf ("PDP (NUXI) Endian");
|
||||
break;
|
||||
default:
|
||||
printf ("Unknown Endian");
|
||||
break;
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
tmp = COMPILED_BYTEORDER;
|
||||
printf ("Compile time detection: ");
|
||||
switch (tmp)
|
||||
{
|
||||
case BIG_ENDIAN:
|
||||
printf ("Big Endian");
|
||||
break;
|
||||
case LITTLE_ENDIAN:
|
||||
printf ("Little Endian");
|
||||
break;
|
||||
case PDP_ENDIAN:
|
||||
printf ("PDP (NUXI) Endian");
|
||||
break;
|
||||
default:
|
||||
printf ("Unknown Endian");
|
||||
break;
|
||||
}
|
||||
#if defined(ENDIAN_GUESSED_SAFE)
|
||||
printf (" (Safe guess)");
|
||||
#elif defined(ENDIAN_ASSUMED_UNSAFE)
|
||||
printf (" (Unsafe assumption)");
|
||||
#endif
|
||||
printf ("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,580 @@
|
||||
/*
|
||||
* anorm_dots.h
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
// 0
|
||||
{ 1.23, 1.30, 1.47, 1.35, 1.56, 1.71, 1.37, 1.38,
|
||||
1.59, 1.60, 1.79, 1.97, 1.88, 1.92, 1.79, 1.02,
|
||||
0.93, 1.07, 0.82, 0.87, 0.88, 0.94, 0.96, 1.14,
|
||||
1.11, 0.82, 0.83, 0.89, 0.89, 0.86, 0.94, 0.91,
|
||||
1.00, 1.21, 0.98, 1.48, 1.30, 1.57, 0.96, 1.07,
|
||||
1.14, 1.60, 1.61, 1.40, 1.37, 1.72, 1.78, 1.79,
|
||||
1.93, 1.99, 1.90, 1.68, 1.71, 1.86, 1.60, 1.68,
|
||||
1.78, 1.86, 1.93, 1.99, 1.97, 1.44, 1.22, 1.49,
|
||||
0.93, 0.99, 0.99, 1.23, 1.22, 1.44, 1.49, 0.89,
|
||||
0.89, 0.97, 0.91, 0.98, 1.19, 0.82, 0.76, 0.82,
|
||||
0.71, 0.72, 0.73, 0.76, 0.79, 0.86, 0.83, 0.72,
|
||||
0.76, 0.76, 0.89, 0.82, 0.89, 0.82, 0.89, 0.91,
|
||||
0.83, 0.96, 1.14, 0.97, 1.40, 1.19, 0.98, 0.94,
|
||||
1.00, 1.07, 1.37, 1.21, 1.48, 1.30, 1.57, 1.61,
|
||||
1.37, 0.86, 0.83, 0.91, 0.82, 0.82, 0.88, 0.89,
|
||||
0.96, 1.14, 0.98, 0.87, 0.93, 0.94, 1.02, 1.30,
|
||||
1.07, 1.35, 1.38, 1.11, 1.56, 1.92, 1.79, 1.79,
|
||||
1.59, 1.60, 1.72, 1.90, 1.79, 0.80, 0.85, 0.79,
|
||||
0.93, 0.80, 0.85, 0.77, 0.74, 0.72, 0.77, 0.74,
|
||||
0.72, 0.70, 0.70, 0.71, 0.76, 0.73, 0.79, 0.79,
|
||||
0.73, 0.76, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 1
|
||||
{ 1.26, 1.26, 1.48, 1.23, 1.50, 1.71, 1.14, 1.19,
|
||||
1.38, 1.46, 1.64, 1.94, 1.87, 1.84, 1.71, 1.02,
|
||||
0.92, 1.00, 0.79, 0.85, 0.84, 0.91, 0.90, 0.98,
|
||||
0.99, 0.77, 0.77, 0.83, 0.82, 0.79, 0.86, 0.84,
|
||||
0.92, 0.99, 0.91, 1.24, 1.03, 1.33, 0.88, 0.94,
|
||||
0.97, 1.41, 1.39, 1.18, 1.11, 1.51, 1.61, 1.59,
|
||||
1.80, 1.91, 1.76, 1.54, 1.65, 1.76, 1.70, 1.70,
|
||||
1.85, 1.85, 1.97, 1.99, 1.93, 1.28, 1.09, 1.39,
|
||||
0.92, 0.97, 0.99, 1.18, 1.26, 1.52, 1.48, 0.83,
|
||||
0.85, 0.90, 0.88, 0.93, 1.00, 0.77, 0.73, 0.78,
|
||||
0.72, 0.71, 0.74, 0.75, 0.79, 0.86, 0.81, 0.75,
|
||||
0.81, 0.79, 0.96, 0.88, 0.94, 0.86, 0.93, 0.92,
|
||||
0.85, 1.08, 1.33, 1.05, 1.55, 1.31, 1.01, 1.05,
|
||||
1.27, 1.31, 1.60, 1.47, 1.70, 1.54, 1.76, 1.76,
|
||||
1.57, 0.93, 0.90, 0.99, 0.88, 0.88, 0.95, 0.97,
|
||||
1.11, 1.39, 1.20, 0.92, 0.97, 1.01, 1.10, 1.39,
|
||||
1.22, 1.51, 1.58, 1.32, 1.64, 1.97, 1.85, 1.91,
|
||||
1.77, 1.74, 1.88, 1.99, 1.91, 0.79, 0.86, 0.80,
|
||||
0.94, 0.84, 0.88, 0.74, 0.74, 0.71, 0.82, 0.77,
|
||||
0.76, 0.70, 0.73, 0.72, 0.73, 0.70, 0.74, 0.85,
|
||||
0.77, 0.82, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 2
|
||||
{ 1.34, 1.27, 1.53, 1.17, 1.46, 1.71, 0.98, 1.05,
|
||||
1.20, 1.34, 1.48, 1.86, 1.82, 1.71, 1.62, 1.09,
|
||||
0.94, 0.99, 0.79, 0.85, 0.82, 0.90, 0.87, 0.93,
|
||||
0.96, 0.76, 0.74, 0.79, 0.76, 0.74, 0.79, 0.78,
|
||||
0.85, 0.92, 0.85, 1.00, 0.93, 1.06, 0.81, 0.86,
|
||||
0.89, 1.16, 1.12, 0.97, 0.95, 1.28, 1.38, 1.35,
|
||||
1.60, 1.77, 1.57, 1.33, 1.50, 1.58, 1.69, 1.63,
|
||||
1.82, 1.74, 1.91, 1.92, 1.80, 1.04, 0.97, 1.21,
|
||||
0.90, 0.93, 0.97, 1.05, 1.21, 1.48, 1.37, 0.77,
|
||||
0.80, 0.84, 0.85, 0.88, 0.92, 0.73, 0.71, 0.74,
|
||||
0.74, 0.71, 0.75, 0.73, 0.79, 0.84, 0.78, 0.79,
|
||||
0.86, 0.81, 1.05, 0.94, 0.99, 0.90, 0.95, 0.92,
|
||||
0.86, 1.24, 1.44, 1.14, 1.59, 1.34, 1.02, 1.27,
|
||||
1.50, 1.49, 1.80, 1.69, 1.86, 1.72, 1.87, 1.80,
|
||||
1.69, 1.00, 0.98, 1.23, 0.95, 0.96, 1.09, 1.16,
|
||||
1.37, 1.63, 1.46, 0.99, 1.10, 1.25, 1.24, 1.51,
|
||||
1.41, 1.67, 1.77, 1.55, 1.72, 1.95, 1.89, 1.98,
|
||||
1.91, 1.86, 1.97, 1.99, 1.94, 0.81, 0.89, 0.85,
|
||||
0.98, 0.90, 0.94, 0.75, 0.78, 0.73, 0.89, 0.83,
|
||||
0.82, 0.72, 0.77, 0.76, 0.72, 0.70, 0.71, 0.91,
|
||||
0.83, 0.89, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 3
|
||||
{ 1.46, 1.34, 1.60, 1.16, 1.46, 1.71, 0.94, 0.99,
|
||||
1.05, 1.26, 1.33, 1.74, 1.76, 1.57, 1.54, 1.23,
|
||||
0.98, 1.05, 0.83, 0.89, 0.84, 0.92, 0.87, 0.91,
|
||||
0.96, 0.78, 0.74, 0.79, 0.72, 0.72, 0.75, 0.76,
|
||||
0.80, 0.88, 0.83, 0.94, 0.87, 0.95, 0.76, 0.80,
|
||||
0.82, 0.97, 0.96, 0.89, 0.88, 1.08, 1.11, 1.10,
|
||||
1.37, 1.59, 1.37, 1.07, 1.27, 1.34, 1.57, 1.45,
|
||||
1.69, 1.55, 1.77, 1.79, 1.60, 0.93, 0.90, 0.99,
|
||||
0.86, 0.87, 0.93, 0.96, 1.07, 1.35, 1.18, 0.73,
|
||||
0.76, 0.77, 0.81, 0.82, 0.85, 0.70, 0.71, 0.72,
|
||||
0.78, 0.73, 0.77, 0.73, 0.79, 0.82, 0.76, 0.83,
|
||||
0.90, 0.84, 1.18, 0.98, 1.03, 0.92, 0.95, 0.90,
|
||||
0.86, 1.32, 1.45, 1.15, 1.53, 1.27, 0.99, 1.42,
|
||||
1.65, 1.58, 1.93, 1.83, 1.94, 1.81, 1.88, 1.74,
|
||||
1.70, 1.19, 1.17, 1.44, 1.11, 1.15, 1.36, 1.41,
|
||||
1.61, 1.81, 1.67, 1.22, 1.34, 1.50, 1.42, 1.65,
|
||||
1.61, 1.82, 1.91, 1.75, 1.80, 1.89, 1.89, 1.98,
|
||||
1.99, 1.94, 1.98, 1.92, 1.87, 0.86, 0.95, 0.92,
|
||||
1.14, 0.98, 1.03, 0.79, 0.84, 0.77, 0.97, 0.90,
|
||||
0.89, 0.76, 0.82, 0.82, 0.74, 0.72, 0.71, 0.98,
|
||||
0.89, 0.97, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 4
|
||||
{ 1.60, 1.44, 1.68, 1.22, 1.49, 1.71, 0.93, 0.99,
|
||||
0.99, 1.23, 1.22, 1.60, 1.68, 1.44, 1.49, 1.40,
|
||||
1.14, 1.19, 0.89, 0.96, 0.89, 0.97, 0.89, 0.91,
|
||||
0.98, 0.82, 0.76, 0.82, 0.71, 0.72, 0.73, 0.76,
|
||||
0.79, 0.86, 0.83, 0.91, 0.83, 0.89, 0.72, 0.76,
|
||||
0.76, 0.89, 0.89, 0.82, 0.82, 0.98, 0.96, 0.97,
|
||||
1.14, 1.40, 1.19, 0.94, 1.00, 1.07, 1.37, 1.21,
|
||||
1.48, 1.30, 1.57, 1.61, 1.37, 0.86, 0.83, 0.91,
|
||||
0.82, 0.82, 0.88, 0.89, 0.96, 1.14, 0.98, 0.70,
|
||||
0.72, 0.73, 0.77, 0.76, 0.79, 0.70, 0.72, 0.71,
|
||||
0.82, 0.77, 0.80, 0.74, 0.79, 0.80, 0.74, 0.87,
|
||||
0.93, 0.85, 1.23, 1.02, 1.02, 0.93, 0.93, 0.87,
|
||||
0.85, 1.30, 1.35, 1.07, 1.38, 1.11, 0.94, 1.47,
|
||||
1.71, 1.56, 1.97, 1.88, 1.92, 1.79, 1.79, 1.59,
|
||||
1.60, 1.30, 1.35, 1.56, 1.37, 1.38, 1.59, 1.60,
|
||||
1.79, 1.92, 1.79, 1.48, 1.57, 1.72, 1.61, 1.78,
|
||||
1.79, 1.93, 1.99, 1.90, 1.86, 1.78, 1.86, 1.93,
|
||||
1.99, 1.97, 1.90, 1.79, 1.72, 0.94, 1.07, 1.00,
|
||||
1.37, 1.21, 1.30, 0.86, 0.91, 0.83, 1.14, 0.98,
|
||||
0.96, 0.82, 0.88, 0.89, 0.79, 0.76, 0.73, 1.07,
|
||||
0.94, 1.11, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 5
|
||||
{ 1.74, 1.57, 1.76, 1.33, 1.54, 1.71, 0.94, 1.05,
|
||||
0.99, 1.26, 1.16, 1.46, 1.60, 1.34, 1.46, 1.59,
|
||||
1.37, 1.37, 0.97, 1.11, 0.96, 1.10, 0.95, 0.94,
|
||||
1.08, 0.89, 0.82, 0.88, 0.72, 0.76, 0.75, 0.80,
|
||||
0.80, 0.88, 0.87, 0.91, 0.83, 0.87, 0.72, 0.76,
|
||||
0.74, 0.83, 0.84, 0.78, 0.79, 0.96, 0.89, 0.92,
|
||||
0.98, 1.23, 1.05, 0.86, 0.92, 0.95, 1.11, 0.98,
|
||||
1.22, 1.03, 1.34, 1.42, 1.14, 0.79, 0.77, 0.84,
|
||||
0.78, 0.76, 0.82, 0.82, 0.89, 0.97, 0.90, 0.70,
|
||||
0.71, 0.71, 0.73, 0.72, 0.74, 0.73, 0.76, 0.72,
|
||||
0.86, 0.81, 0.82, 0.76, 0.79, 0.77, 0.73, 0.90,
|
||||
0.95, 0.86, 1.18, 1.03, 0.98, 0.92, 0.90, 0.83,
|
||||
0.84, 1.19, 1.17, 0.98, 1.15, 0.97, 0.89, 1.42,
|
||||
1.65, 1.44, 1.93, 1.83, 1.81, 1.67, 1.61, 1.36,
|
||||
1.41, 1.32, 1.45, 1.58, 1.57, 1.53, 1.74, 1.70,
|
||||
1.88, 1.94, 1.81, 1.69, 1.77, 1.87, 1.79, 1.89,
|
||||
1.92, 1.98, 1.99, 1.98, 1.89, 1.65, 1.80, 1.82,
|
||||
1.91, 1.94, 1.75, 1.61, 1.50, 1.07, 1.34, 1.27,
|
||||
1.60, 1.45, 1.55, 0.93, 0.99, 0.90, 1.35, 1.18,
|
||||
1.07, 0.87, 0.93, 0.96, 0.85, 0.82, 0.77, 1.15,
|
||||
0.99, 1.27, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 6
|
||||
{ 1.86, 1.71, 1.82, 1.48, 1.62, 1.71, 0.98, 1.20,
|
||||
1.05, 1.34, 1.17, 1.34, 1.53, 1.27, 1.46, 1.77,
|
||||
1.60, 1.57, 1.16, 1.38, 1.12, 1.35, 1.06, 1.00,
|
||||
1.28, 0.97, 0.89, 0.95, 0.76, 0.81, 0.79, 0.86,
|
||||
0.85, 0.92, 0.93, 0.93, 0.85, 0.87, 0.74, 0.78,
|
||||
0.74, 0.79, 0.82, 0.76, 0.79, 0.96, 0.85, 0.90,
|
||||
0.94, 1.09, 0.99, 0.81, 0.85, 0.89, 0.95, 0.90,
|
||||
0.99, 0.94, 1.10, 1.24, 0.98, 0.75, 0.73, 0.78,
|
||||
0.74, 0.72, 0.77, 0.76, 0.82, 0.89, 0.83, 0.73,
|
||||
0.71, 0.71, 0.71, 0.70, 0.72, 0.77, 0.80, 0.74,
|
||||
0.90, 0.85, 0.84, 0.78, 0.79, 0.75, 0.73, 0.92,
|
||||
0.95, 0.86, 1.05, 0.99, 0.94, 0.90, 0.86, 0.79,
|
||||
0.81, 1.00, 0.98, 0.91, 0.96, 0.89, 0.83, 1.27,
|
||||
1.50, 1.23, 1.80, 1.69, 1.63, 1.46, 1.37, 1.09,
|
||||
1.16, 1.24, 1.44, 1.49, 1.69, 1.59, 1.80, 1.69,
|
||||
1.87, 1.86, 1.72, 1.82, 1.91, 1.94, 1.92, 1.95,
|
||||
1.99, 1.98, 1.91, 1.97, 1.89, 1.51, 1.72, 1.67,
|
||||
1.77, 1.86, 1.55, 1.41, 1.25, 1.33, 1.58, 1.50,
|
||||
1.80, 1.63, 1.74, 1.04, 1.21, 0.97, 1.48, 1.37,
|
||||
1.21, 0.93, 0.97, 1.05, 0.92, 0.88, 0.84, 1.14,
|
||||
1.02, 1.34, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 7
|
||||
{ 1.94, 1.84, 1.87, 1.64, 1.71, 1.71, 1.14, 1.38,
|
||||
1.19, 1.46, 1.23, 1.26, 1.48, 1.26, 1.50, 1.91,
|
||||
1.80, 1.76, 1.41, 1.61, 1.39, 1.59, 1.33, 1.24,
|
||||
1.51, 1.18, 0.97, 1.11, 0.82, 0.88, 0.86, 0.94,
|
||||
0.92, 0.99, 1.03, 0.98, 0.91, 0.90, 0.79, 0.84,
|
||||
0.77, 0.79, 0.84, 0.77, 0.83, 0.99, 0.85, 0.91,
|
||||
0.92, 1.02, 1.00, 0.79, 0.80, 0.86, 0.88, 0.84,
|
||||
0.92, 0.88, 0.97, 1.10, 0.94, 0.74, 0.71, 0.74,
|
||||
0.72, 0.70, 0.73, 0.72, 0.76, 0.82, 0.77, 0.77,
|
||||
0.73, 0.74, 0.71, 0.70, 0.73, 0.83, 0.85, 0.78,
|
||||
0.92, 0.88, 0.86, 0.81, 0.79, 0.74, 0.75, 0.92,
|
||||
0.93, 0.85, 0.96, 0.94, 0.88, 0.86, 0.81, 0.75,
|
||||
0.79, 0.93, 0.90, 0.85, 0.88, 0.82, 0.77, 1.05,
|
||||
1.27, 0.99, 1.60, 1.47, 1.39, 1.20, 1.11, 0.95,
|
||||
0.97, 1.08, 1.33, 1.31, 1.70, 1.55, 1.76, 1.57,
|
||||
1.76, 1.70, 1.54, 1.85, 1.97, 1.91, 1.99, 1.97,
|
||||
1.99, 1.91, 1.77, 1.88, 1.85, 1.39, 1.64, 1.51,
|
||||
1.58, 1.74, 1.32, 1.22, 1.01, 1.54, 1.76, 1.65,
|
||||
1.93, 1.70, 1.85, 1.28, 1.39, 1.09, 1.52, 1.48,
|
||||
1.26, 0.97, 0.99, 1.18, 1.00, 0.93, 0.90, 1.05,
|
||||
1.01, 1.31, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 8
|
||||
{ 1.97, 1.92, 1.88, 1.79, 1.79, 1.71, 1.37, 1.59,
|
||||
1.38, 1.60, 1.35, 1.23, 1.47, 1.30, 1.56, 1.99,
|
||||
1.93, 1.90, 1.60, 1.78, 1.61, 1.79, 1.57, 1.48,
|
||||
1.72, 1.40, 1.14, 1.37, 0.89, 0.96, 0.94, 1.07,
|
||||
1.00, 1.21, 1.30, 1.14, 0.98, 0.96, 0.86, 0.91,
|
||||
0.83, 0.82, 0.88, 0.82, 0.89, 1.11, 0.87, 0.94,
|
||||
0.93, 1.02, 1.07, 0.80, 0.79, 0.85, 0.82, 0.80,
|
||||
0.87, 0.85, 0.93, 1.02, 0.93, 0.77, 0.72, 0.74,
|
||||
0.71, 0.70, 0.70, 0.71, 0.72, 0.77, 0.74, 0.82,
|
||||
0.76, 0.79, 0.72, 0.73, 0.76, 0.89, 0.89, 0.82,
|
||||
0.93, 0.91, 0.86, 0.83, 0.79, 0.73, 0.76, 0.91,
|
||||
0.89, 0.83, 0.89, 0.89, 0.82, 0.82, 0.76, 0.72,
|
||||
0.76, 0.86, 0.83, 0.79, 0.82, 0.76, 0.73, 0.94,
|
||||
1.00, 0.91, 1.37, 1.21, 1.14, 0.98, 0.96, 0.88,
|
||||
0.89, 0.96, 1.14, 1.07, 1.60, 1.40, 1.61, 1.37,
|
||||
1.57, 1.48, 1.30, 1.78, 1.93, 1.79, 1.99, 1.92,
|
||||
1.90, 1.79, 1.59, 1.72, 1.79, 1.30, 1.56, 1.35,
|
||||
1.38, 1.60, 1.11, 1.07, 0.94, 1.68, 1.86, 1.71,
|
||||
1.97, 1.68, 1.86, 1.44, 1.49, 1.22, 1.44, 1.49,
|
||||
1.22, 0.99, 0.99, 1.23, 1.19, 0.98, 0.97, 0.97,
|
||||
0.98, 1.19, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 9
|
||||
{ 1.94, 1.97, 1.87, 1.91, 1.85, 1.71, 1.60, 1.77,
|
||||
1.58, 1.74, 1.51, 1.26, 1.48, 1.39, 1.64, 1.99,
|
||||
1.97, 1.99, 1.70, 1.85, 1.76, 1.91, 1.76, 1.70,
|
||||
1.88, 1.55, 1.33, 1.57, 0.96, 1.08, 1.05, 1.31,
|
||||
1.27, 1.47, 1.54, 1.39, 1.20, 1.11, 0.93, 0.99,
|
||||
0.90, 0.88, 0.95, 0.88, 0.97, 1.32, 0.92, 1.01,
|
||||
0.97, 1.10, 1.22, 0.84, 0.80, 0.88, 0.79, 0.79,
|
||||
0.85, 0.86, 0.92, 1.02, 0.94, 0.82, 0.76, 0.77,
|
||||
0.72, 0.73, 0.70, 0.72, 0.71, 0.74, 0.74, 0.88,
|
||||
0.81, 0.85, 0.75, 0.77, 0.82, 0.94, 0.93, 0.86,
|
||||
0.92, 0.92, 0.86, 0.85, 0.79, 0.74, 0.79, 0.88,
|
||||
0.85, 0.81, 0.82, 0.83, 0.77, 0.78, 0.73, 0.71,
|
||||
0.75, 0.79, 0.77, 0.74, 0.77, 0.73, 0.70, 0.86,
|
||||
0.92, 0.84, 1.14, 0.99, 0.98, 0.91, 0.90, 0.84,
|
||||
0.83, 0.88, 0.97, 0.94, 1.41, 1.18, 1.39, 1.11,
|
||||
1.33, 1.24, 1.03, 1.61, 1.80, 1.59, 1.91, 1.84,
|
||||
1.76, 1.64, 1.38, 1.51, 1.71, 1.26, 1.50, 1.23,
|
||||
1.19, 1.46, 0.99, 1.00, 0.91, 1.70, 1.85, 1.65,
|
||||
1.93, 1.54, 1.76, 1.52, 1.48, 1.26, 1.28, 1.39,
|
||||
1.09, 0.99, 0.97, 1.18, 1.31, 1.01, 1.05, 0.90,
|
||||
0.93, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 10
|
||||
{ 1.86, 1.95, 1.82, 1.98, 1.89, 1.71, 1.80, 1.91,
|
||||
1.77, 1.86, 1.67, 1.34, 1.53, 1.51, 1.72, 1.92,
|
||||
1.91, 1.99, 1.69, 1.82, 1.80, 1.94, 1.87, 1.86,
|
||||
1.97, 1.59, 1.44, 1.69, 1.05, 1.24, 1.27, 1.49,
|
||||
1.50, 1.69, 1.72, 1.63, 1.46, 1.37, 1.00, 1.23,
|
||||
0.98, 0.95, 1.09, 0.96, 1.16, 1.55, 0.99, 1.25,
|
||||
1.10, 1.24, 1.41, 0.90, 0.85, 0.94, 0.79, 0.81,
|
||||
0.85, 0.89, 0.94, 1.09, 0.98, 0.89, 0.82, 0.83,
|
||||
0.74, 0.77, 0.72, 0.76, 0.73, 0.75, 0.78, 0.94,
|
||||
0.86, 0.91, 0.79, 0.83, 0.89, 0.99, 0.95, 0.90,
|
||||
0.90, 0.92, 0.84, 0.86, 0.79, 0.75, 0.81, 0.85,
|
||||
0.80, 0.78, 0.76, 0.77, 0.73, 0.74, 0.71, 0.71,
|
||||
0.73, 0.74, 0.74, 0.71, 0.76, 0.72, 0.70, 0.79,
|
||||
0.85, 0.78, 0.98, 0.92, 0.93, 0.85, 0.87, 0.82,
|
||||
0.79, 0.81, 0.89, 0.86, 1.16, 0.97, 1.12, 0.95,
|
||||
1.06, 1.00, 0.93, 1.38, 1.60, 1.35, 1.77, 1.71,
|
||||
1.57, 1.48, 1.20, 1.28, 1.62, 1.27, 1.46, 1.17,
|
||||
1.05, 1.34, 0.96, 0.99, 0.90, 1.63, 1.74, 1.50,
|
||||
1.80, 1.33, 1.58, 1.48, 1.37, 1.21, 1.04, 1.21,
|
||||
0.97, 0.97, 0.93, 1.05, 1.34, 1.02, 1.14, 0.84,
|
||||
0.88, 0.92, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 11
|
||||
{ 1.74, 1.89, 1.76, 1.98, 1.89, 1.71, 1.93, 1.99,
|
||||
1.91, 1.94, 1.82, 1.46, 1.60, 1.65, 1.80, 1.79,
|
||||
1.77, 1.92, 1.57, 1.69, 1.74, 1.87, 1.88, 1.94,
|
||||
1.98, 1.53, 1.45, 1.70, 1.18, 1.32, 1.42, 1.58,
|
||||
1.65, 1.83, 1.81, 1.81, 1.67, 1.61, 1.19, 1.44,
|
||||
1.17, 1.11, 1.36, 1.15, 1.41, 1.75, 1.22, 1.50,
|
||||
1.34, 1.42, 1.61, 0.98, 0.92, 1.03, 0.83, 0.86,
|
||||
0.89, 0.95, 0.98, 1.23, 1.14, 0.97, 0.89, 0.90,
|
||||
0.78, 0.82, 0.76, 0.82, 0.77, 0.79, 0.84, 0.98,
|
||||
0.90, 0.98, 0.83, 0.89, 0.97, 1.03, 0.95, 0.92,
|
||||
0.86, 0.90, 0.82, 0.86, 0.79, 0.77, 0.84, 0.81,
|
||||
0.76, 0.76, 0.72, 0.73, 0.70, 0.72, 0.71, 0.73,
|
||||
0.73, 0.72, 0.74, 0.71, 0.78, 0.74, 0.72, 0.75,
|
||||
0.80, 0.76, 0.94, 0.88, 0.91, 0.83, 0.87, 0.84,
|
||||
0.79, 0.76, 0.82, 0.80, 0.97, 0.89, 0.96, 0.88,
|
||||
0.95, 0.94, 0.87, 1.11, 1.37, 1.10, 1.59, 1.57,
|
||||
1.37, 1.33, 1.05, 1.08, 1.54, 1.34, 1.46, 1.16,
|
||||
0.99, 1.26, 0.96, 1.05, 0.92, 1.45, 1.55, 1.27,
|
||||
1.60, 1.07, 1.34, 1.35, 1.18, 1.07, 0.93, 0.99,
|
||||
0.90, 0.93, 0.87, 0.96, 1.27, 0.99, 1.15, 0.77,
|
||||
0.82, 0.85, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 12
|
||||
{ 1.60, 1.78, 1.68, 1.93, 1.86, 1.71, 1.97, 1.99,
|
||||
1.99, 1.97, 1.93, 1.60, 1.68, 1.78, 1.86, 1.61,
|
||||
1.57, 1.79, 1.37, 1.48, 1.59, 1.72, 1.79, 1.92,
|
||||
1.90, 1.38, 1.35, 1.60, 1.23, 1.30, 1.47, 1.56,
|
||||
1.71, 1.88, 1.79, 1.92, 1.79, 1.79, 1.30, 1.56,
|
||||
1.35, 1.37, 1.59, 1.38, 1.60, 1.90, 1.48, 1.72,
|
||||
1.57, 1.61, 1.79, 1.21, 1.00, 1.30, 0.89, 0.94,
|
||||
0.96, 1.07, 1.14, 1.40, 1.37, 1.14, 0.96, 0.98,
|
||||
0.82, 0.88, 0.82, 0.89, 0.83, 0.86, 0.91, 1.02,
|
||||
0.93, 1.07, 0.87, 0.94, 1.11, 1.02, 0.93, 0.93,
|
||||
0.82, 0.87, 0.80, 0.85, 0.79, 0.80, 0.85, 0.77,
|
||||
0.72, 0.74, 0.71, 0.70, 0.70, 0.71, 0.72, 0.77,
|
||||
0.74, 0.72, 0.76, 0.73, 0.82, 0.79, 0.76, 0.73,
|
||||
0.79, 0.76, 0.93, 0.86, 0.91, 0.83, 0.89, 0.89,
|
||||
0.82, 0.72, 0.76, 0.76, 0.89, 0.82, 0.89, 0.82,
|
||||
0.89, 0.91, 0.83, 0.96, 1.14, 0.97, 1.40, 1.44,
|
||||
1.19, 1.22, 0.99, 0.98, 1.49, 1.44, 1.49, 1.22,
|
||||
0.99, 1.23, 0.98, 1.19, 0.97, 1.21, 1.30, 1.00,
|
||||
1.37, 0.94, 1.07, 1.14, 0.98, 0.96, 0.86, 0.91,
|
||||
0.83, 0.88, 0.82, 0.89, 1.11, 0.94, 1.07, 0.73,
|
||||
0.76, 0.79, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 13
|
||||
{ 1.46, 1.65, 1.60, 1.82, 1.80, 1.71, 1.93, 1.91,
|
||||
1.99, 1.94, 1.98, 1.74, 1.76, 1.89, 1.89, 1.42,
|
||||
1.34, 1.61, 1.11, 1.22, 1.36, 1.50, 1.61, 1.81,
|
||||
1.75, 1.15, 1.17, 1.41, 1.18, 1.19, 1.42, 1.44,
|
||||
1.65, 1.83, 1.67, 1.94, 1.81, 1.88, 1.32, 1.58,
|
||||
1.45, 1.57, 1.74, 1.53, 1.70, 1.98, 1.69, 1.87,
|
||||
1.77, 1.79, 1.92, 1.45, 1.27, 1.55, 0.97, 1.07,
|
||||
1.11, 1.34, 1.37, 1.59, 1.60, 1.35, 1.07, 1.18,
|
||||
0.86, 0.93, 0.87, 0.96, 0.90, 0.93, 0.99, 1.03,
|
||||
0.95, 1.15, 0.90, 0.99, 1.27, 0.98, 0.90, 0.92,
|
||||
0.78, 0.83, 0.77, 0.84, 0.79, 0.82, 0.86, 0.73,
|
||||
0.71, 0.73, 0.72, 0.70, 0.73, 0.72, 0.76, 0.81,
|
||||
0.76, 0.76, 0.82, 0.77, 0.89, 0.85, 0.82, 0.75,
|
||||
0.80, 0.80, 0.94, 0.88, 0.94, 0.87, 0.95, 0.96,
|
||||
0.88, 0.72, 0.74, 0.76, 0.83, 0.78, 0.84, 0.79,
|
||||
0.87, 0.91, 0.83, 0.89, 0.98, 0.92, 1.23, 1.34,
|
||||
1.05, 1.16, 0.99, 0.96, 1.46, 1.57, 1.54, 1.33,
|
||||
1.05, 1.26, 1.08, 1.37, 1.10, 0.98, 1.03, 0.92,
|
||||
1.14, 0.86, 0.95, 0.97, 0.90, 0.89, 0.79, 0.84,
|
||||
0.77, 0.82, 0.76, 0.82, 0.97, 0.89, 0.98, 0.71,
|
||||
0.72, 0.74, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 14
|
||||
{ 1.34, 1.51, 1.53, 1.67, 1.72, 1.71, 1.80, 1.77,
|
||||
1.91, 1.86, 1.98, 1.86, 1.82, 1.95, 1.89, 1.24,
|
||||
1.10, 1.41, 0.95, 0.99, 1.09, 1.25, 1.37, 1.63,
|
||||
1.55, 0.96, 0.98, 1.16, 1.05, 1.00, 1.27, 1.23,
|
||||
1.50, 1.69, 1.46, 1.86, 1.72, 1.87, 1.24, 1.49,
|
||||
1.44, 1.69, 1.80, 1.59, 1.69, 1.97, 1.82, 1.94,
|
||||
1.91, 1.92, 1.99, 1.63, 1.50, 1.74, 1.16, 1.33,
|
||||
1.38, 1.58, 1.60, 1.77, 1.80, 1.48, 1.21, 1.37,
|
||||
0.90, 0.97, 0.93, 1.05, 0.97, 1.04, 1.21, 0.99,
|
||||
0.95, 1.14, 0.92, 1.02, 1.34, 0.94, 0.86, 0.90,
|
||||
0.74, 0.79, 0.75, 0.81, 0.79, 0.84, 0.86, 0.71,
|
||||
0.71, 0.73, 0.76, 0.73, 0.77, 0.74, 0.80, 0.85,
|
||||
0.78, 0.81, 0.89, 0.84, 0.97, 0.92, 0.88, 0.79,
|
||||
0.85, 0.86, 0.98, 0.92, 1.00, 0.93, 1.06, 1.12,
|
||||
0.95, 0.74, 0.74, 0.78, 0.79, 0.76, 0.82, 0.79,
|
||||
0.87, 0.93, 0.85, 0.85, 0.94, 0.90, 1.09, 1.27,
|
||||
0.99, 1.17, 1.05, 0.96, 1.46, 1.71, 1.62, 1.48,
|
||||
1.20, 1.34, 1.28, 1.57, 1.35, 0.90, 0.94, 0.85,
|
||||
0.98, 0.81, 0.89, 0.89, 0.83, 0.82, 0.75, 0.78,
|
||||
0.73, 0.77, 0.72, 0.76, 0.89, 0.83, 0.91, 0.71,
|
||||
0.70, 0.72, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
},
|
||||
|
||||
// 15
|
||||
{ 1.26, 1.39, 1.48, 1.51, 1.64, 1.71, 1.60, 1.58,
|
||||
1.77, 1.74, 1.91, 1.94, 1.87, 1.97, 1.85, 1.10,
|
||||
0.97, 1.22, 0.88, 0.92, 0.95, 1.01, 1.11, 1.39,
|
||||
1.32, 0.88, 0.90, 0.97, 0.96, 0.93, 1.05, 0.99,
|
||||
1.27, 1.47, 1.20, 1.70, 1.54, 1.76, 1.08, 1.31,
|
||||
1.33, 1.70, 1.76, 1.55, 1.57, 1.88, 1.85, 1.91,
|
||||
1.97, 1.99, 1.99, 1.70, 1.65, 1.85, 1.41, 1.54,
|
||||
1.61, 1.76, 1.80, 1.91, 1.93, 1.52, 1.26, 1.48,
|
||||
0.92, 0.99, 0.97, 1.18, 1.09, 1.28, 1.39, 0.94,
|
||||
0.93, 1.05, 0.92, 1.01, 1.31, 0.88, 0.81, 0.86,
|
||||
0.72, 0.75, 0.74, 0.79, 0.79, 0.86, 0.85, 0.71,
|
||||
0.73, 0.75, 0.82, 0.77, 0.83, 0.78, 0.85, 0.88,
|
||||
0.81, 0.88, 0.97, 0.90, 1.18, 1.00, 0.93, 0.86,
|
||||
0.92, 0.94, 1.14, 0.99, 1.24, 1.03, 1.33, 1.39,
|
||||
1.11, 0.79, 0.77, 0.84, 0.79, 0.77, 0.84, 0.83,
|
||||
0.90, 0.98, 0.91, 0.85, 0.92, 0.91, 1.02, 1.26,
|
||||
1.00, 1.23, 1.19, 0.99, 1.50, 1.84, 1.71, 1.64,
|
||||
1.38, 1.46, 1.51, 1.76, 1.59, 0.84, 0.88, 0.80,
|
||||
0.94, 0.79, 0.86, 0.82, 0.77, 0.76, 0.74, 0.74,
|
||||
0.71, 0.73, 0.70, 0.72, 0.82, 0.77, 0.85, 0.74,
|
||||
0.70, 0.73, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00,
|
||||
1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00
|
||||
}
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* anorms.h
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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,0 +1,178 @@
|
||||
/*
|
||||
* arch_def.h
|
||||
* platform specific definitions
|
||||
* - standalone header
|
||||
* - doesn't and must not include any other headers
|
||||
* - shouldn't depend on compiler.h, q_stdinc.h, or
|
||||
* any other headers
|
||||
*
|
||||
* Copyright (C) 2007-2016 O.Sezer <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ARCHDEFS_H
|
||||
#define ARCHDEFS_H
|
||||
|
||||
|
||||
#if defined(__DJGPP__) || defined(__MSDOS__) || defined(__DOS__) || defined(_MSDOS)
|
||||
|
||||
# if !defined(PLATFORM_DOS)
|
||||
# define PLATFORM_DOS 1
|
||||
# endif
|
||||
|
||||
#elif defined(__OS2__) || defined(__EMX__)
|
||||
|
||||
# if !defined(PLATFORM_OS2)
|
||||
# define PLATFORM_OS2 1
|
||||
# endif
|
||||
|
||||
#elif defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(__NT__) || defined(_Windows)
|
||||
|
||||
# if !defined(PLATFORM_WINDOWS)
|
||||
# define PLATFORM_WINDOWS 1
|
||||
# endif
|
||||
|
||||
#elif defined(__APPLE__) && defined(__MACH__) /* Mac OS X */
|
||||
|
||||
# if !defined(PLATFORM_OSX)
|
||||
# define PLATFORM_OSX 1
|
||||
# endif
|
||||
|
||||
#elif defined(macintosh) /* Mac OS classic */
|
||||
|
||||
# if !defined(PLATFORM_MAC)
|
||||
# define PLATFORM_MAC 1
|
||||
# endif
|
||||
|
||||
#elif defined(__MORPHOS__) || defined(__AROS__) || defined(AMIGAOS) || \
|
||||
defined(__amigaos__) || defined(__amigaos4__) ||defined(__amigados__) || \
|
||||
defined(AMIGA) || defined(_AMIGA) || defined(__AMIGA__)
|
||||
|
||||
# if !defined(PLATFORM_AMIGA)
|
||||
# define PLATFORM_AMIGA 1
|
||||
# endif
|
||||
|
||||
#elif defined(__riscos__)
|
||||
|
||||
# if !defined(PLATFORM_RISCOS)
|
||||
# define PLATFORM_RISCOS 1
|
||||
# endif
|
||||
|
||||
#elif defined(__HAIKU__)
|
||||
|
||||
# if !defined(PLATFORM_HAIKU)
|
||||
# define PLATFORM_HAIKU 1
|
||||
# endif
|
||||
|
||||
#else /* here goes the unix platforms */
|
||||
|
||||
#if defined(__unix) || defined(__unix__) || defined(unix) || \
|
||||
defined(__linux__) || defined(__linux) || \
|
||||
defined(__FreeBSD__) || defined(__DragonFly__) || \
|
||||
defined(__FreeBSD_kernel__) /* Debian GNU/kFreeBSD */ || \
|
||||
defined(__OpenBSD__) || defined(__NetBSD__) || \
|
||||
defined(__hpux) || defined(__hpux__) || defined(_hpux) || \
|
||||
defined(__sun) || defined(sun) || \
|
||||
defined(__sgi) || defined(sgi) || defined(__sgi__) || \
|
||||
defined(__GNU__) /* GNU/Hurd */ || \
|
||||
defined(__QNX__) || defined(__QNXNTO__)
|
||||
# if !defined(PLATFORM_UNIX)
|
||||
# define PLATFORM_UNIX 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* PLATFORM_xxx */
|
||||
|
||||
|
||||
#if defined (PLATFORM_OSX) /* OS X is unix-based */
|
||||
# if !defined(PLATFORM_UNIX)
|
||||
# define PLATFORM_UNIX 2
|
||||
# endif
|
||||
#endif /* OS X -> PLATFORM_UNIX */
|
||||
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || \
|
||||
defined(__FreeBSD_kernel__) /* Debian GNU/kFreeBSD */ || \
|
||||
defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
# if !defined(PLATFORM_BSD)
|
||||
# define PLATFORM_BSD 1
|
||||
# endif
|
||||
#endif /* PLATFORM_BSD (for convenience) */
|
||||
|
||||
|
||||
#if defined(PLATFORM_AMIGA) && !defined(PLATFORM_AMIGAOS3)
|
||||
# if !defined(__MORPHOS__) && !defined(__AROS__) && !defined(__amigaos4__)
|
||||
# define PLATFORM_AMIGAOS3 1
|
||||
# endif
|
||||
#endif /* PLATFORM_AMIGAOS3 (for convenience) */
|
||||
|
||||
|
||||
#if defined(_WIN64)
|
||||
# define PLATFORM_STRING "Win64"
|
||||
#elif defined(PLATFORM_WINDOWS)
|
||||
# define PLATFORM_STRING "Windows"
|
||||
#elif defined(PLATFORM_DOS)
|
||||
# define PLATFORM_STRING "DOS"
|
||||
#elif defined(PLATFORM_OS2)
|
||||
# define PLATFORM_STRING "OS/2"
|
||||
#elif defined(__linux__) || defined(__linux)
|
||||
# define PLATFORM_STRING "Linux"
|
||||
#elif defined(__DragonFly__)
|
||||
# define PLATFORM_STRING "DragonFly"
|
||||
#elif defined(__FreeBSD__)
|
||||
# define PLATFORM_STRING "FreeBSD"
|
||||
#elif defined(__NetBSD__)
|
||||
# define PLATFORM_STRING "NetBSD"
|
||||
#elif defined(__OpenBSD__)
|
||||
# define PLATFORM_STRING "OpenBSD"
|
||||
#elif defined(__MORPHOS__)
|
||||
# define PLATFORM_STRING "MorphOS"
|
||||
#elif defined(__AROS__)
|
||||
# define PLATFORM_STRING "AROS"
|
||||
#elif defined(__amigaos4__)
|
||||
# define PLATFORM_STRING "AmigaOS4"
|
||||
#elif defined(PLATFORM_AMIGA)
|
||||
# define PLATFORM_STRING "AmigaOS"
|
||||
#elif defined(__QNX__) || defined(__QNXNTO__)
|
||||
# define PLATFORM_STRING "QNX"
|
||||
#elif defined(PLATFORM_OSX)
|
||||
# define PLATFORM_STRING "MacOSX"
|
||||
#elif defined(PLATFORM_MAC)
|
||||
# define PLATFORM_STRING "MacOS"
|
||||
#elif defined(__hpux) || defined(__hpux__) || defined(_hpux)
|
||||
# define PLATFORM_STRING "HP-UX"
|
||||
#elif (defined(__sun) || defined(sun)) && (defined(__svr4__) || defined(__SVR4))
|
||||
# define PLATFORM_STRING "Solaris"
|
||||
#elif defined(__sun) || defined(sun)
|
||||
# define PLATFORM_STRING "SunOS"
|
||||
#elif defined(__sgi) || defined(sgi) || defined(__sgi__)
|
||||
# define PLATFORM_STRING "Irix"
|
||||
#elif defined(PLATFORM_RISCOS)
|
||||
# define PLATFORM_STRING "RiscOS"
|
||||
#elif defined(__GNU__)
|
||||
# define PLATFORM_STRING "GNU/Hurd"
|
||||
#elif defined(PLATFORM_HAIKU)
|
||||
# define PLATFORM_STRING "Haiku"
|
||||
#elif defined(PLATFORM_UNIX)
|
||||
# define PLATFORM_STRING "Unix"
|
||||
#else
|
||||
# define PLATFORM_STRING "Unknown"
|
||||
# warning "Platform is UNKNOWN."
|
||||
#endif /* PLATFORM_STRING */
|
||||
|
||||
#endif /* ARCHDEFS_H */
|
||||
|
||||
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
* Background music handling for Quakespasm (adapted from uHexen2)
|
||||
* Handles streaming music as raw sound samples and runs the midi driver
|
||||
*
|
||||
* Copyright (C) 1999-2005 Id Software, Inc.
|
||||
* Copyright (C) 2010-2018 O.Sezer <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "quakedef.hpp"
|
||||
#include "snd_codec.hpp"
|
||||
#include "bgmusic.hpp"
|
||||
|
||||
#define MUSIC_DIRNAME "music"
|
||||
|
||||
qboolean bgmloop;
|
||||
cvar_t bgm_extmusic = {"bgm_extmusic", "1", CVAR_ARCHIVE};
|
||||
|
||||
static qboolean no_extmusic= false;
|
||||
static float old_volume = -1.0f;
|
||||
|
||||
typedef enum _bgm_player
|
||||
{
|
||||
BGM_NONE = -1,
|
||||
BGM_MIDIDRV = 1,
|
||||
BGM_STREAMER
|
||||
} bgm_player_t;
|
||||
|
||||
typedef struct music_handler_s
|
||||
{
|
||||
unsigned int type; /* 1U << n (see snd_codec.h) */
|
||||
bgm_player_t player; /* Enumerated bgm player type */
|
||||
int is_available; /* -1 means not present */
|
||||
const char *ext; /* Expected file extension */
|
||||
const char *dir; /* Where to look for music file */
|
||||
struct music_handler_s *next;
|
||||
} music_handler_t;
|
||||
|
||||
static music_handler_t wanted_handlers[] =
|
||||
{
|
||||
{ CODECTYPE_VORBIS,BGM_STREAMER,-1, "ogg", MUSIC_DIRNAME, NULL },
|
||||
{ CODECTYPE_OPUS, BGM_STREAMER, -1, "opus", MUSIC_DIRNAME, NULL },
|
||||
{ CODECTYPE_MP3, BGM_STREAMER, -1, "mp3", MUSIC_DIRNAME, NULL },
|
||||
{ CODECTYPE_FLAC, BGM_STREAMER, -1, "flac", MUSIC_DIRNAME, NULL },
|
||||
{ CODECTYPE_WAV, BGM_STREAMER, -1, "wav", MUSIC_DIRNAME, NULL },
|
||||
{ CODECTYPE_MOD, BGM_STREAMER, -1, "it", MUSIC_DIRNAME, NULL },
|
||||
{ CODECTYPE_MOD, BGM_STREAMER, -1, "s3m", MUSIC_DIRNAME, NULL },
|
||||
{ CODECTYPE_MOD, BGM_STREAMER, -1, "xm", MUSIC_DIRNAME, NULL },
|
||||
{ CODECTYPE_MOD, BGM_STREAMER, -1, "mod", MUSIC_DIRNAME, NULL },
|
||||
{ CODECTYPE_UMX, BGM_STREAMER, -1, "umx", MUSIC_DIRNAME, NULL },
|
||||
{ CODECTYPE_NONE, BGM_NONE, -1, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static music_handler_t *music_handlers = NULL;
|
||||
|
||||
#define ANY_CODECTYPE 0xFFFFFFFF
|
||||
#define CDRIP_TYPES (CODECTYPE_VORBIS | CODECTYPE_MP3 | CODECTYPE_FLAC | CODECTYPE_WAV | CODECTYPE_OPUS)
|
||||
#define CDRIPTYPE(x) (((x) & CDRIP_TYPES) != 0)
|
||||
|
||||
static snd_stream_t *bgmstream = NULL;
|
||||
|
||||
static void BGM_Play_f (void)
|
||||
{
|
||||
if (Cmd_Argc() == 2) {
|
||||
BGM_Play (Cmd_Argv(1));
|
||||
}
|
||||
else {
|
||||
Con_Printf ("music <musicfile>\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void BGM_Pause_f (void)
|
||||
{
|
||||
BGM_Pause ();
|
||||
}
|
||||
|
||||
static void BGM_Resume_f (void)
|
||||
{
|
||||
BGM_Resume ();
|
||||
}
|
||||
|
||||
static void BGM_Loop_f (void)
|
||||
{
|
||||
if (Cmd_Argc() == 2) {
|
||||
if (q_strcasecmp(Cmd_Argv(1), "0") == 0 ||
|
||||
q_strcasecmp(Cmd_Argv(1),"off") == 0)
|
||||
bgmloop = false;
|
||||
else if (q_strcasecmp(Cmd_Argv(1), "1") == 0 ||
|
||||
q_strcasecmp(Cmd_Argv(1),"on") == 0)
|
||||
bgmloop = true;
|
||||
else if (q_strcasecmp(Cmd_Argv(1),"toggle") == 0)
|
||||
bgmloop = !bgmloop;
|
||||
|
||||
if (bgmstream) bgmstream->loop = bgmloop;
|
||||
}
|
||||
|
||||
if (bgmloop)
|
||||
Con_Printf("Music will be looped\n");
|
||||
else
|
||||
Con_Printf("Music will not be looped\n");
|
||||
}
|
||||
|
||||
static void BGM_Stop_f (void)
|
||||
{
|
||||
BGM_Stop();
|
||||
}
|
||||
|
||||
static void BGM_Jump_f (void)
|
||||
{
|
||||
if (Cmd_Argc() != 2) {
|
||||
Con_Printf ("music_jump <ordernum>\n");
|
||||
}
|
||||
else if (bgmstream) {
|
||||
S_CodecJumpToOrder(bgmstream, atoi(Cmd_Argv(1)));
|
||||
}
|
||||
}
|
||||
|
||||
qboolean BGM_Init (void)
|
||||
{
|
||||
music_handler_t *handlers = NULL;
|
||||
int i;
|
||||
|
||||
Cvar_RegisterVariable(&bgm_extmusic);
|
||||
Cmd_AddCommand("music", BGM_Play_f);
|
||||
Cmd_AddCommand("music_pause", BGM_Pause_f);
|
||||
Cmd_AddCommand("music_resume", BGM_Resume_f);
|
||||
Cmd_AddCommand("music_loop", BGM_Loop_f);
|
||||
Cmd_AddCommand("music_stop", BGM_Stop_f);
|
||||
Cmd_AddCommand("music_jump", BGM_Jump_f);
|
||||
|
||||
if (COM_CheckParm("-noextmusic") != 0)
|
||||
no_extmusic = true;
|
||||
|
||||
bgmloop = true;
|
||||
|
||||
for (i = 0; wanted_handlers[i].type != CODECTYPE_NONE; i++)
|
||||
{
|
||||
switch (wanted_handlers[i].player)
|
||||
{
|
||||
case BGM_MIDIDRV:
|
||||
/* not supported in quake */
|
||||
break;
|
||||
case BGM_STREAMER:
|
||||
wanted_handlers[i].is_available =
|
||||
S_CodecIsAvailable(wanted_handlers[i].type);
|
||||
break;
|
||||
case BGM_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (wanted_handlers[i].is_available != -1)
|
||||
{
|
||||
if (handlers)
|
||||
{
|
||||
handlers->next = &wanted_handlers[i];
|
||||
handlers = handlers->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
music_handlers = &wanted_handlers[i];
|
||||
handlers = music_handlers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BGM_Shutdown (void)
|
||||
{
|
||||
BGM_Stop();
|
||||
/* sever our connections to
|
||||
* midi_drv and snd_codec */
|
||||
music_handlers = NULL;
|
||||
}
|
||||
|
||||
static void BGM_Play_noext (const char *filename, unsigned int allowed_types)
|
||||
{
|
||||
char tmp[MAX_QPATH];
|
||||
music_handler_t *handler;
|
||||
|
||||
handler = music_handlers;
|
||||
while (handler)
|
||||
{
|
||||
if (! (handler->type & allowed_types))
|
||||
{
|
||||
handler = handler->next;
|
||||
continue;
|
||||
}
|
||||
if (!handler->is_available)
|
||||
{
|
||||
handler = handler->next;
|
||||
continue;
|
||||
}
|
||||
q_snprintf(tmp, sizeof(tmp), "%s/%s.%s",
|
||||
handler->dir, filename, handler->ext);
|
||||
switch (handler->player)
|
||||
{
|
||||
case BGM_MIDIDRV:
|
||||
/* not supported in quake */
|
||||
break;
|
||||
case BGM_STREAMER:
|
||||
bgmstream = S_CodecOpenStreamType(tmp, handler->type, bgmloop);
|
||||
if (bgmstream)
|
||||
return; /* success */
|
||||
break;
|
||||
case BGM_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
handler = handler->next;
|
||||
}
|
||||
|
||||
Con_Printf("Couldn't handle music file %s\n", filename);
|
||||
}
|
||||
|
||||
void BGM_Play (const char *filename)
|
||||
{
|
||||
char tmp[MAX_QPATH];
|
||||
const char *ext;
|
||||
music_handler_t *handler;
|
||||
|
||||
BGM_Stop();
|
||||
|
||||
if (music_handlers == NULL)
|
||||
return;
|
||||
|
||||
if (!filename || !*filename)
|
||||
{
|
||||
Con_DPrintf("null music file name\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ext = COM_FileGetExtension(filename);
|
||||
if (! *ext) /* try all things */
|
||||
{
|
||||
BGM_Play_noext(filename, ANY_CODECTYPE);
|
||||
return;
|
||||
}
|
||||
|
||||
handler = music_handlers;
|
||||
while (handler)
|
||||
{
|
||||
if (handler->is_available &&
|
||||
!q_strcasecmp(ext, handler->ext))
|
||||
break;
|
||||
handler = handler->next;
|
||||
}
|
||||
if (!handler)
|
||||
{
|
||||
Con_Printf("Unhandled extension for %s\n", filename);
|
||||
return;
|
||||
}
|
||||
q_snprintf(tmp, sizeof(tmp), "%s/%s", handler->dir, filename);
|
||||
switch (handler->player)
|
||||
{
|
||||
case BGM_MIDIDRV:
|
||||
/* not supported in quake */
|
||||
break;
|
||||
case BGM_STREAMER:
|
||||
bgmstream = S_CodecOpenStreamType(tmp, handler->type, bgmloop);
|
||||
if (bgmstream)
|
||||
return; /* success */
|
||||
break;
|
||||
case BGM_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Con_Printf("Couldn't handle music file %s\n", filename);
|
||||
}
|
||||
|
||||
void BGM_PlayCDtrack (byte track, qboolean looping)
|
||||
{
|
||||
/* instead of searching by the order of music_handlers, do so by
|
||||
* the order of searchpath priority: the file from the searchpath
|
||||
* with the highest path_id is most likely from our own gamedir
|
||||
* itself. This way, if a mod has track02 as a *.mp3 file, which
|
||||
* is below *.ogg in the music_handler order, the mp3 will still
|
||||
* have priority over track02.ogg from, say, id1.
|
||||
*/
|
||||
char tmp[MAX_QPATH];
|
||||
const char *ext;
|
||||
unsigned int path_id, prev_id, type;
|
||||
music_handler_t *handler;
|
||||
|
||||
BGM_Stop();
|
||||
if (CDAudio_Play(track, looping) == 0)
|
||||
return; /* success */
|
||||
|
||||
if (music_handlers == NULL)
|
||||
return;
|
||||
|
||||
if (no_extmusic || !bgm_extmusic.value)
|
||||
return;
|
||||
|
||||
prev_id = 0;
|
||||
type = 0;
|
||||
ext = NULL;
|
||||
handler = music_handlers;
|
||||
while (handler)
|
||||
{
|
||||
if (! handler->is_available)
|
||||
goto _next;
|
||||
if (! CDRIPTYPE(handler->type))
|
||||
goto _next;
|
||||
q_snprintf(tmp, sizeof(tmp), "%s/track%02d.%s",
|
||||
MUSIC_DIRNAME, (int)track, handler->ext);
|
||||
if (! COM_FileExists(tmp, &path_id))
|
||||
goto _next;
|
||||
if (path_id > prev_id)
|
||||
{
|
||||
prev_id = path_id;
|
||||
type = handler->type;
|
||||
ext = handler->ext;
|
||||
}
|
||||
_next:
|
||||
handler = handler->next;
|
||||
}
|
||||
if (ext == NULL)
|
||||
Con_Printf("Couldn't find a cdrip for track %d\n", (int)track);
|
||||
else
|
||||
{
|
||||
q_snprintf(tmp, sizeof(tmp), "%s/track%02d.%s",
|
||||
MUSIC_DIRNAME, (int)track, ext);
|
||||
bgmstream = S_CodecOpenStreamType(tmp, type, bgmloop);
|
||||
if (! bgmstream)
|
||||
Con_Printf("Couldn't handle music file %s\n", tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void BGM_Stop (void)
|
||||
{
|
||||
if (bgmstream)
|
||||
{
|
||||
bgmstream->status = STREAM_NONE;
|
||||
S_CodecCloseStream(bgmstream);
|
||||
bgmstream = NULL;
|
||||
s_rawend = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BGM_Pause (void)
|
||||
{
|
||||
if (bgmstream)
|
||||
{
|
||||
if (bgmstream->status == STREAM_PLAY)
|
||||
bgmstream->status = STREAM_PAUSE;
|
||||
}
|
||||
}
|
||||
|
||||
void BGM_Resume (void)
|
||||
{
|
||||
if (bgmstream)
|
||||
{
|
||||
if (bgmstream->status == STREAM_PAUSE)
|
||||
bgmstream->status = STREAM_PLAY;
|
||||
}
|
||||
}
|
||||
|
||||
static void BGM_UpdateStream (void)
|
||||
{
|
||||
qboolean did_rewind = false;
|
||||
int res; /* Number of bytes read. */
|
||||
int bufferSamples;
|
||||
int fileSamples;
|
||||
int fileBytes;
|
||||
byte raw[16384];
|
||||
|
||||
if (bgmstream->status != STREAM_PLAY)
|
||||
return;
|
||||
|
||||
/* don't bother playing anything if musicvolume is 0 */
|
||||
if (bgmvolume.value <= 0)
|
||||
return;
|
||||
|
||||
/* see how many samples should be copied into the raw buffer */
|
||||
if (s_rawend < paintedtime)
|
||||
s_rawend = paintedtime;
|
||||
|
||||
while (s_rawend < paintedtime + MAX_RAW_SAMPLES)
|
||||
{
|
||||
bufferSamples = MAX_RAW_SAMPLES - (s_rawend - paintedtime);
|
||||
|
||||
/* decide how much data needs to be read from the file */
|
||||
fileSamples = bufferSamples * bgmstream->info.rate / shm->speed;
|
||||
if (!fileSamples)
|
||||
return;
|
||||
|
||||
/* our max buffer size */
|
||||
fileBytes = fileSamples * (bgmstream->info.width * bgmstream->info.channels);
|
||||
if (fileBytes > (int) sizeof(raw))
|
||||
{
|
||||
fileBytes = (int) sizeof(raw);
|
||||
fileSamples = fileBytes /
|
||||
(bgmstream->info.width * bgmstream->info.channels);
|
||||
}
|
||||
|
||||
/* Read */
|
||||
res = S_CodecReadStream(bgmstream, fileBytes, raw);
|
||||
if (res < fileBytes)
|
||||
{
|
||||
fileBytes = res;
|
||||
fileSamples = res / (bgmstream->info.width * bgmstream->info.channels);
|
||||
}
|
||||
|
||||
if (res > 0) /* data: add to raw buffer */
|
||||
{
|
||||
S_RawSamples(fileSamples, bgmstream->info.rate,
|
||||
bgmstream->info.width,
|
||||
bgmstream->info.channels,
|
||||
raw, bgmvolume.value);
|
||||
did_rewind = false;
|
||||
}
|
||||
else if (res == 0) /* EOF */
|
||||
{
|
||||
if (bgmloop)
|
||||
{
|
||||
if (did_rewind)
|
||||
{
|
||||
Con_Printf("Stream keeps returning EOF.\n");
|
||||
BGM_Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
res = S_CodecRewindStream(bgmstream);
|
||||
if (res != 0)
|
||||
{
|
||||
Con_Printf("Stream seek error (%i), stopping.\n", res);
|
||||
BGM_Stop();
|
||||
return;
|
||||
}
|
||||
did_rewind = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
BGM_Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else /* res < 0: some read error */
|
||||
{
|
||||
Con_Printf("Stream read error (%i), stopping.\n", res);
|
||||
BGM_Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BGM_Update (void)
|
||||
{
|
||||
if (old_volume != bgmvolume.value)
|
||||
{
|
||||
if (bgmvolume.value < 0)
|
||||
Cvar_SetQuick (&bgmvolume, "0");
|
||||
else if (bgmvolume.value > 1)
|
||||
Cvar_SetQuick (&bgmvolume, "1");
|
||||
old_volume = bgmvolume.value;
|
||||
}
|
||||
if (bgmstream)
|
||||
BGM_UpdateStream ();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Background music handling for Quakespasm (adapted from uHexen2)
|
||||
* Handles streaming music as raw sound samples and runs the midi driver
|
||||
*
|
||||
* Copyright (C) 1999-2005 Id Software, Inc.
|
||||
* Copyright (C) 2010-2012 O.Sezer <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BGMUSIC_H_
|
||||
#define _BGMUSIC_H_
|
||||
|
||||
extern qboolean bgmloop;
|
||||
extern cvar_t bgm_extmusic;
|
||||
|
||||
qboolean BGM_Init (void);
|
||||
void BGM_Shutdown (void);
|
||||
|
||||
void BGM_Play (const char *filename);
|
||||
void BGM_Stop (void);
|
||||
void BGM_Update (void);
|
||||
void BGM_Pause (void);
|
||||
void BGM_Resume (void);
|
||||
|
||||
void BGM_PlayCDtrack (byte track, qboolean looping);
|
||||
|
||||
#endif /* _BGMUSIC_H_ */
|
||||
|
||||
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 __BSPFILE_H
|
||||
#define __BSPFILE_H
|
||||
|
||||
// upper design bounds
|
||||
|
||||
#define MAX_MAP_HULLS 4
|
||||
|
||||
#define MAX_MAP_MODELS 256
|
||||
#define MAX_MAP_BRUSHES 4096
|
||||
#define MAX_MAP_ENTITIES 1024
|
||||
#define MAX_MAP_ENTSTRING 65536
|
||||
|
||||
#define MAX_MAP_PLANES 32767
|
||||
#define MAX_MAP_NODES 32767 // because negative shorts are contents
|
||||
#define MAX_MAP_CLIPNODES 32767
|
||||
//#define MAX_MAP_LEAFS 80000 //johnfitz -- was 8192
|
||||
#define MAX_MAP_VERTS 65535
|
||||
#define MAX_MAP_FACES 65535
|
||||
#define MAX_MAP_MARKSURFACES 65535
|
||||
#define MAX_MAP_TEXINFO 4096
|
||||
#define MAX_MAP_EDGES 256000
|
||||
#define MAX_MAP_SURFEDGES 512000
|
||||
#define MAX_MAP_TEXTURES 512
|
||||
#define MAX_MAP_MIPTEX 0x200000
|
||||
#define MAX_MAP_LIGHTING 0x100000
|
||||
#define MAX_MAP_VISIBILITY 0x100000
|
||||
|
||||
#define MAX_MAP_PORTALS 65536
|
||||
|
||||
// key / value pair sizes
|
||||
|
||||
#define MAX_KEY 32
|
||||
#define MAX_VALUE 1024
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
||||
#define BSPVERSION 29
|
||||
|
||||
/* RMQ support (2PSB). 32bits instead of shorts for all but bbox sizes (which
|
||||
* still use shorts) */
|
||||
#define BSP2VERSION_2PSB (('B' << 24) | ('S' << 16) | ('P' << 8) | '2')
|
||||
|
||||
/* BSP2 support. 32bits instead of shorts for everything (bboxes use floats) */
|
||||
#define BSP2VERSION_BSP2 (('B' << 0) | ('S' << 8) | ('P' << 16) | ('2'<<24))
|
||||
|
||||
// Quake64
|
||||
#define BSPVERSION_QUAKE64 (('Q' << 24) | ('6' << 16) | ('4' << 8) | ' ')
|
||||
|
||||
#define TOOLVERSION 2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fileofs, filelen;
|
||||
} lump_t;
|
||||
|
||||
#define LUMP_ENTITIES 0
|
||||
#define LUMP_PLANES 1
|
||||
#define LUMP_TEXTURES 2
|
||||
#define LUMP_VERTEXES 3
|
||||
#define LUMP_VISIBILITY 4
|
||||
#define LUMP_NODES 5
|
||||
#define LUMP_TEXINFO 6
|
||||
#define LUMP_FACES 7
|
||||
#define LUMP_LIGHTING 8
|
||||
#define LUMP_CLIPNODES 9
|
||||
#define LUMP_LEAFS 10
|
||||
#define LUMP_MARKSURFACES 11
|
||||
#define LUMP_EDGES 12
|
||||
#define LUMP_SURFEDGES 13
|
||||
#define LUMP_MODELS 14
|
||||
|
||||
#define HEADER_LUMPS 15
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float mins[3], maxs[3];
|
||||
float origin[3];
|
||||
int headnode[MAX_MAP_HULLS];
|
||||
int visleafs; // not including the solid leaf 0
|
||||
int firstface, numfaces;
|
||||
} dmodel_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int version;
|
||||
lump_t lumps[HEADER_LUMPS];
|
||||
} dheader_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int nummiptex;
|
||||
int dataofs[4]; // [nummiptex]
|
||||
} dmiptexlump_t;
|
||||
|
||||
#define MIPLEVELS 4
|
||||
typedef struct miptex_s
|
||||
{
|
||||
char name[16];
|
||||
unsigned width, height;
|
||||
unsigned offsets[MIPLEVELS]; // four mip maps stored
|
||||
} miptex_t;
|
||||
|
||||
// Quake64
|
||||
typedef struct miptex64_s
|
||||
{
|
||||
char name[16];
|
||||
unsigned width, height;
|
||||
unsigned shift;
|
||||
unsigned offsets[MIPLEVELS]; // four mip maps stored
|
||||
} miptex64_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float point[3];
|
||||
} dvertex_t;
|
||||
|
||||
|
||||
// 0-2 are axial planes
|
||||
#define PLANE_X 0
|
||||
#define PLANE_Y 1
|
||||
#define PLANE_Z 2
|
||||
|
||||
// 3-5 are non-axial planes snapped to the nearest
|
||||
#define PLANE_ANYX 3
|
||||
#define PLANE_ANYY 4
|
||||
#define PLANE_ANYZ 5
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float normal[3];
|
||||
float dist;
|
||||
int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
|
||||
} dplane_t;
|
||||
|
||||
|
||||
#define CONTENTS_EMPTY -1
|
||||
#define CONTENTS_SOLID -2
|
||||
#define CONTENTS_WATER -3
|
||||
#define CONTENTS_SLIME -4
|
||||
#define CONTENTS_LAVA -5
|
||||
#define CONTENTS_SKY -6
|
||||
#define CONTENTS_ORIGIN -7 // removed at csg time
|
||||
#define CONTENTS_CLIP -8 // changed to contents_solid
|
||||
|
||||
#define CONTENTS_CURRENT_0 -9
|
||||
#define CONTENTS_CURRENT_90 -10
|
||||
#define CONTENTS_CURRENT_180 -11
|
||||
#define CONTENTS_CURRENT_270 -12
|
||||
#define CONTENTS_CURRENT_UP -13
|
||||
#define CONTENTS_CURRENT_DOWN -14
|
||||
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_i386.h too !!!
|
||||
typedef struct
|
||||
{
|
||||
int planenum;
|
||||
short children[2]; // negative numbers are -(leafs+1), not nodes
|
||||
short mins[3]; // for sphere culling
|
||||
short maxs[3];
|
||||
unsigned short firstface;
|
||||
unsigned short numfaces; // counting both sides
|
||||
} dsnode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int planenum;
|
||||
int children[2]; // negative numbers are -(leafs+1), not nodes
|
||||
short mins[3]; // for sphere culling
|
||||
short maxs[3];
|
||||
unsigned int firstface;
|
||||
unsigned int numfaces; // counting both sides
|
||||
} dl1node_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int planenum;
|
||||
int children[2]; // negative numbers are -(leafs+1), not nodes
|
||||
float mins[3]; // for sphere culling
|
||||
float maxs[3];
|
||||
unsigned int firstface;
|
||||
unsigned int numfaces; // counting both sides
|
||||
} dl2node_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int planenum;
|
||||
short children[2]; // negative numbers are contents
|
||||
} dsclipnode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int planenum;
|
||||
int children[2]; // negative numbers are contents
|
||||
} dlclipnode_t;
|
||||
|
||||
|
||||
typedef struct texinfo_s
|
||||
{
|
||||
float vecs[2][4]; // [s/t][xyz offset]
|
||||
int miptex;
|
||||
int flags;
|
||||
} texinfo_t;
|
||||
#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision
|
||||
#define TEX_MISSING 2 // johnfitz -- this texinfo does not have a texture
|
||||
|
||||
// note that edge 0 is never used, because negative edge nums are used for
|
||||
// counterclockwise use of the edge in a face
|
||||
typedef struct
|
||||
{
|
||||
unsigned short v[2]; // vertex numbers
|
||||
} dsedge_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int v[2]; // vertex numbers
|
||||
} dledge_t;
|
||||
|
||||
#define MAXLIGHTMAPS 4
|
||||
typedef struct
|
||||
{
|
||||
short planenum;
|
||||
short side;
|
||||
|
||||
int firstedge; // we must support > 64k edges
|
||||
short numedges;
|
||||
short texinfo;
|
||||
|
||||
// lighting info
|
||||
byte styles[MAXLIGHTMAPS];
|
||||
int lightofs; // start of [numstyles*surfsize] samples
|
||||
} dsface_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int planenum;
|
||||
int side;
|
||||
|
||||
int firstedge; // we must support > 64k edges
|
||||
int numedges;
|
||||
int texinfo;
|
||||
|
||||
// lighting info
|
||||
byte styles[MAXLIGHTMAPS];
|
||||
int lightofs; // start of [numstyles*surfsize] samples
|
||||
} dlface_t;
|
||||
|
||||
#define AMBIENT_WATER 0
|
||||
#define AMBIENT_SKY 1
|
||||
#define AMBIENT_SLIME 2
|
||||
#define AMBIENT_LAVA 3
|
||||
|
||||
#define NUM_AMBIENTS 4 // automatic ambient sounds
|
||||
|
||||
// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas
|
||||
// all other leafs need visibility info
|
||||
typedef struct
|
||||
{
|
||||
int contents;
|
||||
int visofs; // -1 = no visibility info
|
||||
|
||||
short mins[3]; // for frustum culling
|
||||
short maxs[3];
|
||||
|
||||
unsigned short firstmarksurface;
|
||||
unsigned short nummarksurfaces;
|
||||
|
||||
byte ambient_level[NUM_AMBIENTS];
|
||||
} dsleaf_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int contents;
|
||||
int visofs; // -1 = no visibility info
|
||||
|
||||
short mins[3]; // for frustum culling
|
||||
short maxs[3];
|
||||
|
||||
unsigned int firstmarksurface;
|
||||
unsigned int nummarksurfaces;
|
||||
|
||||
byte ambient_level[NUM_AMBIENTS];
|
||||
} dl1leaf_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int contents;
|
||||
int visofs; // -1 = no visibility info
|
||||
|
||||
float mins[3]; // for frustum culling
|
||||
float maxs[3];
|
||||
|
||||
unsigned int firstmarksurface;
|
||||
unsigned int nummarksurfaces;
|
||||
|
||||
byte ambient_level[NUM_AMBIENTS];
|
||||
} dl2leaf_t;
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
#ifndef QUAKE_GAME
|
||||
|
||||
#define ANGLE_UP -1
|
||||
#define ANGLE_DOWN -2
|
||||
|
||||
|
||||
// the utilities get to be lazy and just use large static arrays
|
||||
|
||||
extern int nummodels;
|
||||
extern dmodel_t dmodels[MAX_MAP_MODELS];
|
||||
|
||||
extern int visdatasize;
|
||||
extern byte dvisdata[MAX_MAP_VISIBILITY];
|
||||
|
||||
extern int lightdatasize;
|
||||
extern byte dlightdata[MAX_MAP_LIGHTING];
|
||||
|
||||
extern int texdatasize;
|
||||
extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t)
|
||||
|
||||
extern int entdatasize;
|
||||
extern char dentdata[MAX_MAP_ENTSTRING];
|
||||
|
||||
//extern int numleafs;
|
||||
//extern dleaf_t dleafs[MAX_MAP_LEAFS];
|
||||
|
||||
extern int numplanes;
|
||||
extern dplane_t dplanes[MAX_MAP_PLANES];
|
||||
|
||||
extern int numvertexes;
|
||||
extern dvertex_t dvertexes[MAX_MAP_VERTS];
|
||||
|
||||
extern int numnodes;
|
||||
extern dnode_t dnodes[MAX_MAP_NODES];
|
||||
|
||||
extern int numtexinfo;
|
||||
extern texinfo_t texinfo[MAX_MAP_TEXINFO];
|
||||
|
||||
extern int numfaces;
|
||||
extern dface_t dfaces[MAX_MAP_FACES];
|
||||
|
||||
extern int numclipnodes;
|
||||
extern dclipnode_t dclipnodes[MAX_MAP_CLIPNODES];
|
||||
|
||||
extern int numedges;
|
||||
extern dedge_t dedges[MAX_MAP_EDGES];
|
||||
|
||||
extern int nummarksurfaces;
|
||||
extern unsigned short dmarksurfaces[MAX_MAP_MARKSURFACES];
|
||||
|
||||
extern int numsurfedges;
|
||||
extern int dsurfedges[MAX_MAP_SURFEDGES];
|
||||
|
||||
|
||||
void DecompressVis (byte *in, byte *decompressed);
|
||||
int CompressVis (byte *vis, byte *dest);
|
||||
|
||||
void LoadBSPFile (char *filename);
|
||||
void WriteBSPFile (char *filename);
|
||||
void PrintBSPFileSizes (void);
|
||||
|
||||
//===============
|
||||
|
||||
|
||||
typedef struct epair_s
|
||||
{
|
||||
struct epair_s *next;
|
||||
char *key;
|
||||
char *value;
|
||||
} epair_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t origin;
|
||||
int firstbrush;
|
||||
int numbrushes;
|
||||
epair_t *epairs;
|
||||
} entity_t;
|
||||
|
||||
extern int num_entities;
|
||||
extern entity_t entities[MAX_MAP_ENTITIES];
|
||||
|
||||
void ParseEntities (void);
|
||||
void UnparseEntities (void);
|
||||
|
||||
void SetKeyValue (entity_t *ent, char *key, char *value);
|
||||
char *ValueForKey (entity_t *ent, char *key);
|
||||
// will return "" if not present
|
||||
|
||||
vec_t FloatForKey (entity_t *ent, char *key);
|
||||
void GetVectorForKey (entity_t *ent, char *key, vec3_t vec);
|
||||
|
||||
epair_t *ParseEpair (void);
|
||||
|
||||
#endif /* QUAKE_GAME */
|
||||
|
||||
#endif /* __BSPFILE_H */
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* cd_null.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "quakedef.h"
|
||||
|
||||
int CDAudio_Play(byte track, qboolean looping)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CDAudio_Stop(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CDAudio_Pause(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CDAudio_Resume(void)
|
||||
{
|
||||
}
|
||||
|
||||
void CDAudio_Update(void)
|
||||
{
|
||||
}
|
||||
|
||||
int CDAudio_Init(void)
|
||||
{
|
||||
Con_Printf("CDAudio disabled at compile time\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CDAudio_Shutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,593 @@
|
||||
/*
|
||||
* cd_sdl.c
|
||||
*
|
||||
* Copyright (C) 1996-1997 Id Software, Inc.
|
||||
* Taken from the Twilight project with modifications
|
||||
* to make it work with Hexen II: Hammer of Thyrion.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#if defined(SDL_FRAMEWORK) || defined(NO_SDL_CONFIG)
|
||||
#if defined(USE_SDL2)
|
||||
#include <SDL2/SDL.h>
|
||||
#else
|
||||
#include <SDL/SDL.h>
|
||||
#endif
|
||||
#else
|
||||
#include "SDL.h"
|
||||
#endif
|
||||
|
||||
#ifndef SDL_INIT_CDROM
|
||||
|
||||
/* SDL dropped support for
|
||||
cd audio since v1.3.0 */
|
||||
#pragma message("Warning: SDL CDAudio support disabled")
|
||||
#include "cd_null.c"
|
||||
|
||||
#else /* SDL_INIT_CDROM */
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
static qboolean cdValid = false;
|
||||
static qboolean playing = false;
|
||||
static qboolean wasPlaying = false;
|
||||
static qboolean enabled = true;
|
||||
static qboolean playLooping = false;
|
||||
static byte remap[100];
|
||||
static byte playTrack;
|
||||
static double endOfTrack = -1.0, pausetime = -1.0;
|
||||
static SDL_CD *cd_handle;
|
||||
static int cd_dev = -1;
|
||||
static float old_cdvolume;
|
||||
static qboolean hw_vol_works = true;
|
||||
|
||||
|
||||
static void CDAudio_Eject(void)
|
||||
{
|
||||
if (!cd_handle || !enabled)
|
||||
return;
|
||||
|
||||
#ifdef __linux__
|
||||
SDL_CDStop(cd_handle); /* see CDAudio_Stop() */
|
||||
#endif
|
||||
if (SDL_CDEject(cd_handle) < 0)
|
||||
Con_Printf ("Unable to eject CD-ROM: %s\n", SDL_GetError ());
|
||||
}
|
||||
|
||||
static int CDAudio_GetAudioDiskInfo(void)
|
||||
{
|
||||
cdValid = false;
|
||||
|
||||
if (!cd_handle)
|
||||
return -1;
|
||||
|
||||
if ( ! CD_INDRIVE(SDL_CDStatus(cd_handle)) )
|
||||
return -1;
|
||||
|
||||
cdValid = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CDAudio_Play(byte track, qboolean looping)
|
||||
{
|
||||
int len_m, len_s, len_f;
|
||||
|
||||
if (!cd_handle || !enabled)
|
||||
return -1;
|
||||
|
||||
if (!cdValid)
|
||||
{
|
||||
CDAudio_GetAudioDiskInfo();
|
||||
if (!cdValid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
track = remap[track];
|
||||
|
||||
if (track < 1 || track > cd_handle->numtracks)
|
||||
{
|
||||
Con_Printf ("CDAudio_Play: Bad track number %d.\n", track);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cd_handle->track[track-1].type == SDL_DATA_TRACK)
|
||||
{
|
||||
Con_Printf ("CDAudio_Play: track %d is not audio\n", track);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (playing)
|
||||
{
|
||||
if (playTrack == track)
|
||||
return 0;
|
||||
CDAudio_Stop();
|
||||
}
|
||||
|
||||
if (SDL_CDPlay(cd_handle, cd_handle->track[track-1].offset, cd_handle->track[track-1].length) < 0)
|
||||
{
|
||||
Con_Printf ("CDAudio_Play: Unable to play track %d: %s\n", track, SDL_GetError ());
|
||||
return -1;
|
||||
}
|
||||
|
||||
playLooping = looping;
|
||||
playTrack = track;
|
||||
playing = true;
|
||||
|
||||
FRAMES_TO_MSF(cd_handle->track[track-1].length, &len_m, &len_s, &len_f);
|
||||
endOfTrack = realtime + ((double)len_m * 60.0) + (double)len_s + (double)len_f / (double)CD_FPS;
|
||||
|
||||
/* Add the pregap for the next track. This means that disc-at-once CDs
|
||||
* won't loop smoothly, but they wouldn't anyway so it doesn't really
|
||||
* matter. SDL doesn't give us pregap information anyway, so you'll
|
||||
* just have to live with it. */
|
||||
endOfTrack += 2.0;
|
||||
pausetime = -1.0;
|
||||
|
||||
if (bgmvolume.value == 0) /* don't bother advancing */
|
||||
CDAudio_Pause ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CDAudio_Stop(void)
|
||||
{
|
||||
if (!cd_handle || !enabled)
|
||||
return;
|
||||
|
||||
if (!playing)
|
||||
return;
|
||||
|
||||
#ifdef __linux__
|
||||
/* Don't really stop, but just pause: On some devices, the CDROMSTOP
|
||||
* ioctl causes any followup ioctls to fail for a considerable time.
|
||||
* observed with a TSSTcorp CDW/DVD SH-M522C drive with TS05 and TS08
|
||||
* firmware versions running under a 2.6.27.25 kernel, and with a
|
||||
* Samsung DVD r/w drive running under 2.6.35.6 kernel.
|
||||
* Therefore, avoid dead stops if playback may be resumed shortly. */
|
||||
if (SDL_CDPause(cd_handle) < 0)
|
||||
Con_Printf ("CDAudio_Stop: Unable to stop CD-ROM (%s)\n", SDL_GetError());
|
||||
#else
|
||||
if (SDL_CDStop(cd_handle) < 0)
|
||||
Con_Printf ("CDAudio_Stop: Unable to stop CD-ROM (%s)\n", SDL_GetError());
|
||||
#endif
|
||||
|
||||
wasPlaying = false;
|
||||
playing = false;
|
||||
pausetime = -1.0;
|
||||
endOfTrack = -1.0;
|
||||
}
|
||||
|
||||
void CDAudio_Pause(void)
|
||||
{
|
||||
if (!cd_handle || !enabled)
|
||||
return;
|
||||
|
||||
if (!playing)
|
||||
return;
|
||||
|
||||
if (SDL_CDPause(cd_handle) < 0)
|
||||
Con_Printf ("Unable to pause CD-ROM: %s\n", SDL_GetError());
|
||||
|
||||
wasPlaying = playing;
|
||||
playing = false;
|
||||
pausetime = realtime;
|
||||
}
|
||||
|
||||
void CDAudio_Resume(void)
|
||||
{
|
||||
if (!cd_handle || !enabled)
|
||||
return;
|
||||
|
||||
if (!cdValid)
|
||||
return;
|
||||
|
||||
if (!wasPlaying)
|
||||
return;
|
||||
|
||||
if (SDL_CDResume(cd_handle) < 0)
|
||||
Con_Printf ("Unable to resume CD-ROM: %s\n", SDL_GetError());
|
||||
playing = true;
|
||||
endOfTrack += realtime - pausetime;
|
||||
pausetime = -1.0;
|
||||
}
|
||||
|
||||
static int get_first_audiotrk (void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < cd_handle->numtracks; ++i)
|
||||
if (cd_handle->track[i].type != SDL_DATA_TRACK)
|
||||
return ++i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void CD_f (void)
|
||||
{
|
||||
const char *command;
|
||||
int ret, n;
|
||||
|
||||
if (Cmd_Argc() < 2)
|
||||
{
|
||||
Con_Printf("commands:");
|
||||
Con_Printf("on, off, reset, remap, \n");
|
||||
Con_Printf("play, stop, loop, pause, resume\n");
|
||||
Con_Printf("eject, info, next, prev\n");
|
||||
return;
|
||||
}
|
||||
|
||||
command = Cmd_Argv (1);
|
||||
|
||||
if (q_strcasecmp(command, "on") == 0)
|
||||
{
|
||||
enabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "off") == 0)
|
||||
{
|
||||
if (playing)
|
||||
CDAudio_Stop();
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "reset") == 0)
|
||||
{
|
||||
enabled = true;
|
||||
if (playing)
|
||||
CDAudio_Stop();
|
||||
for (n = 0; n < 100; n++)
|
||||
remap[n] = n;
|
||||
CDAudio_GetAudioDiskInfo();
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "remap") == 0)
|
||||
{
|
||||
ret = Cmd_Argc() - 2;
|
||||
if (ret <= 0)
|
||||
{
|
||||
for (n = 1; n < 100; n++)
|
||||
if (remap[n] != n)
|
||||
Con_Printf(" %u -> %u\n", n, remap[n]);
|
||||
return;
|
||||
}
|
||||
for (n = 1; n <= ret; n++)
|
||||
remap[n] = atoi(Cmd_Argv (n + 1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cdValid)
|
||||
{
|
||||
CDAudio_GetAudioDiskInfo();
|
||||
if (!cdValid)
|
||||
{
|
||||
Con_Printf("No CD in player.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "play") == 0)
|
||||
{
|
||||
n = atoi(Cmd_Argv (2));
|
||||
if (n == 0)
|
||||
n = 1;
|
||||
CDAudio_Play((byte)n, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "loop") == 0)
|
||||
{
|
||||
CDAudio_Play((byte)atoi(Cmd_Argv (2)), true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "stop") == 0)
|
||||
{
|
||||
CDAudio_Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "pause") == 0)
|
||||
{
|
||||
CDAudio_Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "resume") == 0)
|
||||
{
|
||||
CDAudio_Resume();
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "eject") == 0)
|
||||
{
|
||||
if (playing)
|
||||
CDAudio_Stop();
|
||||
CDAudio_Eject();
|
||||
cdValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "info") == 0)
|
||||
{
|
||||
int current_min, current_sec, current_frame;
|
||||
int length_min, length_sec, length_frame;
|
||||
|
||||
Con_Printf ("%u tracks\n", cd_handle->numtracks);
|
||||
|
||||
if (playing)
|
||||
Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
|
||||
else if (wasPlaying)
|
||||
Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
|
||||
|
||||
if (playing || wasPlaying)
|
||||
{
|
||||
SDL_CDStatus(cd_handle);
|
||||
FRAMES_TO_MSF(cd_handle->cur_frame, ¤t_min, ¤t_sec, ¤t_frame);
|
||||
FRAMES_TO_MSF(cd_handle->track[playTrack-1].length, &length_min, &length_sec, &length_frame);
|
||||
|
||||
Con_Printf ("Current position: %d:%02d.%02d (of %d:%02d.%02d)\n",
|
||||
current_min, current_sec, current_frame * 60 / CD_FPS,
|
||||
length_min, length_sec, length_frame * 60 / CD_FPS);
|
||||
}
|
||||
Con_Printf("Volume is %f\n", bgmvolume.value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "next") == 0)
|
||||
{
|
||||
if (playTrack == cd_handle->numtracks)
|
||||
playTrack = get_first_audiotrk() - 1;
|
||||
CDAudio_Play(playTrack + 1, playLooping);
|
||||
return;
|
||||
}
|
||||
|
||||
if (q_strcasecmp(command, "prev") == 0)
|
||||
{
|
||||
if (playTrack == get_first_audiotrk())
|
||||
playTrack = cd_handle->numtracks + 1;
|
||||
CDAudio_Play(playTrack - 1, playLooping);
|
||||
return;
|
||||
}
|
||||
|
||||
Con_Printf ("cd: unknown command \"%s\"\n", command);
|
||||
}
|
||||
|
||||
static qboolean CD_GetVolume (void *unused)
|
||||
{
|
||||
/* FIXME: write proper code in here when SDL
|
||||
supports cdrom volume control some day. */
|
||||
return false;
|
||||
}
|
||||
|
||||
static qboolean CD_SetVolume (void *unused)
|
||||
{
|
||||
/* FIXME: write proper code in here when SDL
|
||||
supports cdrom volume control some day. */
|
||||
return false;
|
||||
}
|
||||
|
||||
static qboolean CDAudio_SetVolume (float value)
|
||||
{
|
||||
if (!cd_handle || !enabled)
|
||||
return false;
|
||||
|
||||
old_cdvolume = value;
|
||||
|
||||
if (value == 0.0f)
|
||||
CDAudio_Pause ();
|
||||
else
|
||||
CDAudio_Resume();
|
||||
|
||||
if (!hw_vol_works)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: write proper code in here when SDL
|
||||
supports cdrom volume control some day. */
|
||||
return CD_SetVolume (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void CDAudio_Update(void)
|
||||
{
|
||||
CDstatus curstat;
|
||||
/* static double lastchk;*/
|
||||
|
||||
if (!cd_handle || !enabled)
|
||||
return;
|
||||
|
||||
if (old_cdvolume != bgmvolume.value)
|
||||
CDAudio_SetVolume (bgmvolume.value);
|
||||
|
||||
/* if (playing && realtime > lastchk)*/
|
||||
if (playing && realtime > endOfTrack)
|
||||
{
|
||||
/* lastchk = realtime + 2;*/ /* two seconds between chks */
|
||||
curstat = SDL_CDStatus(cd_handle);
|
||||
if (curstat != CD_PLAYING && curstat != CD_PAUSED)
|
||||
{
|
||||
playing = false;
|
||||
endOfTrack = -1.0;
|
||||
if (playLooping)
|
||||
CDAudio_Play(playTrack, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_cddev_arg (const char *arg)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/* arg should be like "D:\", make sure it is so,
|
||||
* but tolerate args like "D" or "D:", as well. */
|
||||
static char drive[4];
|
||||
if (!arg || ! *arg)
|
||||
return NULL;
|
||||
if (arg[1] != '\0')
|
||||
{
|
||||
if (arg[1] != ':')
|
||||
return NULL;
|
||||
if (arg[2] != '\0')
|
||||
{
|
||||
if (arg[2] != '\\' &&
|
||||
arg[2] != '/')
|
||||
return NULL;
|
||||
if (arg[3] != '\0')
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (*arg >= 'A' && *arg <= 'Z')
|
||||
{
|
||||
drive[0] = *arg;
|
||||
drive[1] = ':';
|
||||
drive[2] = '\\';
|
||||
drive[3] = '\0';
|
||||
return drive;
|
||||
}
|
||||
else if (*arg >= 'a' && *arg <= 'z')
|
||||
{
|
||||
/* make it uppercase for SDL */
|
||||
drive[0] = *arg - ('a' - 'A');
|
||||
drive[1] = ':';
|
||||
drive[2] = '\\';
|
||||
drive[3] = '\0';
|
||||
return drive;
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
if (!arg || ! *arg)
|
||||
return NULL;
|
||||
return arg;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void export_cddev_arg (void)
|
||||
{
|
||||
/* Bad ugly hack to workaround SDL's cdrom device detection.
|
||||
* not needed for windows due to the way SDL_cdrom works. */
|
||||
#if !defined(_WIN32)
|
||||
int i = COM_CheckParm("-cddev");
|
||||
if (i != 0 && i < com_argc - 1 && com_argv[i+1][0] != '\0')
|
||||
{
|
||||
static char arg[64];
|
||||
q_snprintf(arg, sizeof(arg), "SDL_CDROM=%s", com_argv[i+1]);
|
||||
putenv(arg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int CDAudio_Init(void)
|
||||
{
|
||||
int i, sdl_num_drives;
|
||||
|
||||
if (safemode || COM_CheckParm("-nocdaudio"))
|
||||
return -1;
|
||||
|
||||
export_cddev_arg();
|
||||
|
||||
if (SDL_InitSubSystem(SDL_INIT_CDROM) < 0)
|
||||
{
|
||||
Con_Printf("Couldn't init SDL cdrom: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
sdl_num_drives = SDL_CDNumDrives ();
|
||||
Con_Printf ("SDL detected %d CD-ROM drive%c\n", sdl_num_drives,
|
||||
sdl_num_drives == 1 ? ' ' : 's');
|
||||
|
||||
if (sdl_num_drives < 1)
|
||||
return -1;
|
||||
|
||||
if ((i = COM_CheckParm("-cddev")) != 0 && i < com_argc - 1)
|
||||
{
|
||||
const char *userdev = get_cddev_arg(com_argv[i+1]);
|
||||
if (!userdev)
|
||||
{
|
||||
Con_Printf("Invalid argument to -cddev\n");
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < sdl_num_drives; i++)
|
||||
{
|
||||
if (!q_strcasecmp(SDL_CDName(i), userdev))
|
||||
{
|
||||
cd_dev = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cd_dev == -1)
|
||||
{
|
||||
Con_Printf("SDL couldn't find cdrom device %s\n", userdev);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cd_dev == -1)
|
||||
cd_dev = 0; /* default drive */
|
||||
|
||||
cd_handle = SDL_CDOpen(cd_dev);
|
||||
if (!cd_handle)
|
||||
{
|
||||
Con_Printf ("CDAudio_Init: Unable to open CD-ROM drive %s (%s)\n",
|
||||
SDL_CDName(cd_dev), SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
remap[i] = i;
|
||||
enabled = true;
|
||||
old_cdvolume = bgmvolume.value;
|
||||
|
||||
Con_Printf("CDAudio initialized (SDL, using %s)\n", SDL_CDName(cd_dev));
|
||||
|
||||
if (CDAudio_GetAudioDiskInfo())
|
||||
{
|
||||
Con_Printf("CDAudio_Init: No CD in drive\n");
|
||||
cdValid = false;
|
||||
}
|
||||
|
||||
Cmd_AddCommand ("cd", CD_f);
|
||||
|
||||
hw_vol_works = CD_GetVolume (NULL); /* no SDL support at present. */
|
||||
if (hw_vol_works)
|
||||
hw_vol_works = CDAudio_SetVolume (bgmvolume.value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CDAudio_Shutdown(void)
|
||||
{
|
||||
if (!cd_handle)
|
||||
return;
|
||||
CDAudio_Stop();
|
||||
if (hw_vol_works)
|
||||
CD_SetVolume (NULL); /* no SDL support at present. */
|
||||
#ifdef __linux__
|
||||
SDL_CDStop(cd_handle); /* see CDAudio_Stop() */
|
||||
#endif
|
||||
SDL_CDClose(cd_handle);
|
||||
cd_handle = NULL;
|
||||
cd_dev = -1;
|
||||
SDL_QuitSubSystem(SDL_INIT_CDROM);
|
||||
}
|
||||
|
||||
#endif /* SDL_INIT_CDROM */
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 __CDAUDIO_H
|
||||
#define __CDAUDIO_H
|
||||
|
||||
int CDAudio_Init (void);
|
||||
int CDAudio_Play (byte track, qboolean looping);
|
||||
/* returns 0 for success, -1 for failure. */
|
||||
void CDAudio_Stop (void);
|
||||
void CDAudio_Pause (void);
|
||||
void CDAudio_Resume (void);
|
||||
void CDAudio_Shutdown (void);
|
||||
void CDAudio_Update (void);
|
||||
|
||||
#endif /* __CDAUDIO_H */
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* cfgfile.c -- misc reads from the config file
|
||||
*
|
||||
* Copyright (C) 2008-2012 O.Sezer <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
|
||||
static fshandle_t *cfg_file;
|
||||
|
||||
/*
|
||||
===================
|
||||
CFG_ReadCvars
|
||||
|
||||
used for doing early reads from config.cfg searching the list
|
||||
of given cvar names for the user-set values. a temporary
|
||||
solution until we merge a better cvar system.
|
||||
the num_vars argument must be the exact number of strings in the
|
||||
array, otherwise I have nothing against going out of bounds.
|
||||
===================
|
||||
*/
|
||||
void CFG_ReadCvars (const char **vars, int num_vars)
|
||||
{
|
||||
char buff[1024], *tmp;
|
||||
int i, j;
|
||||
|
||||
if (!cfg_file || num_vars < 1)
|
||||
return;
|
||||
|
||||
j = 0;
|
||||
|
||||
do {
|
||||
i = 0;
|
||||
memset (buff, 0, sizeof(buff));
|
||||
// we expect a line in the format that Cvar_WriteVariables
|
||||
// writes to the config file. although I'm trying to be as
|
||||
// much cautious as possible, if the user screws it up by
|
||||
// editing it, it's his fault.
|
||||
if (FS_fgets(buff, sizeof(buff), cfg_file))
|
||||
{
|
||||
// remove end-of-line characters
|
||||
while (buff[i])
|
||||
{
|
||||
if (buff[i] == '\r' || buff[i] == '\n')
|
||||
buff[i] = '\0';
|
||||
// while we're here, replace tabs with spaces
|
||||
if (buff[i] == '\t')
|
||||
buff[i] = ' ';
|
||||
i++;
|
||||
}
|
||||
// go to the last character
|
||||
while (buff[i] == 0 && i > 0)
|
||||
i--;
|
||||
// remove trailing spaces
|
||||
while (i > 0)
|
||||
{
|
||||
if (buff[i] == ' ')
|
||||
{
|
||||
buff[i] = '\0';
|
||||
i--;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// the line must end with a quotation mark
|
||||
if (buff[i] != '\"')
|
||||
continue;
|
||||
buff[i] = '\0';
|
||||
|
||||
for (i = 0; i < num_vars && vars[i]; i++)
|
||||
{
|
||||
// look for the cvar name + one space
|
||||
tmp = strstr(buff, va("%s ",vars[i]));
|
||||
if (tmp != buff)
|
||||
continue;
|
||||
// locate the first quotation mark
|
||||
tmp = strchr(buff, '\"');
|
||||
if (tmp)
|
||||
{
|
||||
Cvar_Set (vars[i], tmp + 1);
|
||||
j++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (j == num_vars)
|
||||
break;
|
||||
|
||||
} while (!FS_feof(cfg_file) && !FS_ferror(cfg_file));
|
||||
|
||||
FS_rewind (cfg_file);
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
CFG_ReadCvarOverrides
|
||||
|
||||
convenience function, reading the "+" command line override
|
||||
values of cvars in the given list. doesn't do anything with
|
||||
the config file.
|
||||
===================
|
||||
*/
|
||||
void CFG_ReadCvarOverrides (const char **vars, int num_vars)
|
||||
{
|
||||
char buff[64];
|
||||
int i, j;
|
||||
|
||||
if (num_vars < 1)
|
||||
return;
|
||||
|
||||
buff[0] = '+';
|
||||
|
||||
for (i = 0; i < num_vars; i++)
|
||||
{
|
||||
q_strlcpy (&buff[1], vars[i], sizeof(buff) - 1);
|
||||
j = COM_CheckParm(buff);
|
||||
if (j != 0 && j < com_argc - 1)
|
||||
{
|
||||
if (com_argv[j + 1][0] != '-' && com_argv[j + 1][0] != '+')
|
||||
Cvar_Set(vars[i], com_argv[j + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CFG_CloseConfig (void)
|
||||
{
|
||||
if (cfg_file)
|
||||
{
|
||||
FS_fclose(cfg_file);
|
||||
Z_Free(cfg_file);
|
||||
cfg_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int CFG_OpenConfig (const char *cfg_name)
|
||||
{
|
||||
FILE *f;
|
||||
long length;
|
||||
qboolean pak;
|
||||
|
||||
CFG_CloseConfig ();
|
||||
|
||||
length = (long) COM_FOpenFile (cfg_name, &f, NULL);
|
||||
pak = file_from_pak;
|
||||
if (length == -1)
|
||||
return -1;
|
||||
|
||||
cfg_file = (fshandle_t *) Z_Malloc(sizeof(fshandle_t));
|
||||
cfg_file->file = f;
|
||||
cfg_file->start = ftell(f);
|
||||
cfg_file->pos = 0;
|
||||
cfg_file->length = length;
|
||||
cfg_file->pak = pak;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* cfgfile.h -- misc reads from the config file
|
||||
*
|
||||
* Copyright (C) 2008-2012 O.Sezer <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __CFGFILE_H
|
||||
#define __CFGFILE_H
|
||||
|
||||
int CFG_OpenConfig (const char *cfg_name);
|
||||
// opens the given config file. only one open config file is
|
||||
// kept: previosly opened one, if any, will be closed.
|
||||
|
||||
void CFG_CloseConfig (void);
|
||||
// closes the currently open config file.
|
||||
|
||||
void CFG_ReadCvars (const char **vars, int num_vars);
|
||||
// reads the values of cvars in the given list from the opened
|
||||
// config file.
|
||||
|
||||
void CFG_ReadCvarOverrides (const char **vars, int num_vars);
|
||||
// convenience function, reading the "+" command line override
|
||||
// values of cvars in the given list. doesn't do anything with
|
||||
// the config file. call this after CFG_ReadCvars() and before
|
||||
// locking your cvars.
|
||||
|
||||
#endif /* __CFGFILE_H */
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// chase.c -- chase camera code
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
cvar_t chase_back = {"chase_back", "100", CVAR_NONE};
|
||||
cvar_t chase_up = {"chase_up", "16", CVAR_NONE};
|
||||
cvar_t chase_right = {"chase_right", "0", CVAR_NONE};
|
||||
cvar_t chase_active = {"chase_active", "0", CVAR_NONE};
|
||||
|
||||
/*
|
||||
==============
|
||||
Chase_Init
|
||||
==============
|
||||
*/
|
||||
void Chase_Init (void)
|
||||
{
|
||||
Cvar_RegisterVariable (&chase_back);
|
||||
Cvar_RegisterVariable (&chase_up);
|
||||
Cvar_RegisterVariable (&chase_right);
|
||||
Cvar_RegisterVariable (&chase_active);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
TraceLine
|
||||
|
||||
TODO: impact on bmodels, monsters
|
||||
==============
|
||||
*/
|
||||
void TraceLine (vec3_t start, vec3_t end, vec3_t impact)
|
||||
{
|
||||
trace_t trace;
|
||||
|
||||
memset (&trace, 0, sizeof(trace));
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
|
||||
|
||||
VectorCopy (trace.endpos, impact);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Chase_UpdateForClient -- johnfitz -- orient client based on camera. called after input
|
||||
==============
|
||||
*/
|
||||
void Chase_UpdateForClient (void)
|
||||
{
|
||||
//place camera
|
||||
|
||||
//assign client angles to camera
|
||||
|
||||
//see where camera points
|
||||
|
||||
//adjust client angles to point at the same place
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Chase_UpdateForDrawing -- johnfitz -- orient camera based on client. called before drawing
|
||||
|
||||
TODO: stay at least 8 units away from all walls in this leaf
|
||||
==============
|
||||
*/
|
||||
void Chase_UpdateForDrawing (void)
|
||||
{
|
||||
int i;
|
||||
vec3_t forward, up, right;
|
||||
vec3_t ideal, crosshair, temp;
|
||||
|
||||
AngleVectors (cl.viewangles, forward, right, up);
|
||||
|
||||
// calc ideal camera location before checking for walls
|
||||
for (i=0 ; i<3 ; i++)
|
||||
ideal[i] = cl.viewent.origin[i]
|
||||
- forward[i]*chase_back.value
|
||||
+ right[i]*chase_right.value;
|
||||
//+ up[i]*chase_up.value;
|
||||
ideal[2] = cl.viewent.origin[2] + chase_up.value;
|
||||
|
||||
// make sure camera is not in or behind a wall
|
||||
TraceLine(r_refdef.vieworg, ideal, temp);
|
||||
if (VectorLength(temp) != 0)
|
||||
VectorCopy(temp, ideal);
|
||||
|
||||
// place camera
|
||||
VectorCopy (ideal, r_refdef.vieworg);
|
||||
|
||||
// find the spot the player is looking at
|
||||
VectorMA (cl.viewent.origin, 1<<20, forward, temp);
|
||||
TraceLine (cl.viewent.origin, temp, crosshair);
|
||||
|
||||
// calculate camera angles to look at the same spot
|
||||
VectorSubtract (crosshair, r_refdef.vieworg, temp);
|
||||
VectorAngles (temp, r_refdef.viewangles);
|
||||
if (r_refdef.viewangles[PITCH] == 90 || r_refdef.viewangles[PITCH] == -90)
|
||||
r_refdef.viewangles[YAW] = cl.viewangles[YAW];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
static void CL_FinishTimeDemo (void);
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
DEMO CODE
|
||||
|
||||
When a demo is playing back, all NET_SendMessages are skipped, and
|
||||
NET_GetMessages are read from the demo file.
|
||||
|
||||
Whenever cl.time gets past the last received message, another message is
|
||||
read from the demo file.
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// from ProQuake: space to fill out the demo header for record at any time
|
||||
static byte *demo_head;
|
||||
static int *demo_head_sizes;
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_ClearSignons
|
||||
==============
|
||||
*/
|
||||
void CL_ClearSignons (void)
|
||||
{
|
||||
VEC_CLEAR (demo_head);
|
||||
VEC_CLEAR (demo_head_sizes);
|
||||
cls.signon = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_StopPlayback
|
||||
|
||||
Called when a demo file runs out, or the user starts a game
|
||||
==============
|
||||
*/
|
||||
void CL_StopPlayback (void)
|
||||
{
|
||||
if (!cls.demoplayback)
|
||||
return;
|
||||
|
||||
fclose (cls.demofile);
|
||||
cls.demoplayback = false;
|
||||
cls.demopaused = false;
|
||||
cls.demofile = NULL;
|
||||
cls.state = ca_disconnected;
|
||||
|
||||
if (cls.timedemo)
|
||||
CL_FinishTimeDemo ();
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_WriteDemoMessage
|
||||
|
||||
Dumps the current net message, prefixed by the length and view angles
|
||||
====================
|
||||
*/
|
||||
static void CL_WriteDemoMessage (void)
|
||||
{
|
||||
int len;
|
||||
int i;
|
||||
float f;
|
||||
|
||||
len = LittleLong (net_message.cursize);
|
||||
fwrite (&len, 4, 1, cls.demofile);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
f = LittleFloat (cl.viewangles[i]);
|
||||
fwrite (&f, 4, 1, cls.demofile);
|
||||
}
|
||||
fwrite (net_message.data, net_message.cursize, 1, cls.demofile);
|
||||
fflush (cls.demofile);
|
||||
}
|
||||
|
||||
static int CL_GetDemoMessage (void)
|
||||
{
|
||||
int r, i;
|
||||
float f;
|
||||
|
||||
if (cls.demopaused)
|
||||
return 0;
|
||||
|
||||
// decide if it is time to grab the next message
|
||||
if (cls.signon == SIGNONS) // always grab until fully connected
|
||||
{
|
||||
if (cls.timedemo)
|
||||
{
|
||||
if (host_framecount == cls.td_lastframe)
|
||||
return 0; // already read this frame's message
|
||||
cls.td_lastframe = host_framecount;
|
||||
// if this is the second frame, grab the real td_starttime
|
||||
// so the bogus time on the first frame doesn't count
|
||||
if (host_framecount == cls.td_startframe + 1)
|
||||
cls.td_starttime = realtime;
|
||||
}
|
||||
else if (/* cl.time > 0 && */ cl.time <= cl.mtime[0])
|
||||
{
|
||||
return 0; // don't need another message yet
|
||||
}
|
||||
}
|
||||
|
||||
// get the next message
|
||||
if (! fread(&net_message.cursize, 4, 1, cls.demofile))
|
||||
Sys_Error ("Demo read error");
|
||||
VectorCopy (cl.mviewangles[0], cl.mviewangles[1]);
|
||||
for (i = 0 ; i < 3 ; i++)
|
||||
{
|
||||
r = fread (&f, 4, 1, cls.demofile);
|
||||
cl.mviewangles[0][i] = LittleFloat (f);
|
||||
}
|
||||
|
||||
net_message.cursize = LittleLong (net_message.cursize);
|
||||
if (net_message.cursize > MAX_MSGLEN)
|
||||
Sys_Error ("Demo message > MAX_MSGLEN");
|
||||
r = fread (net_message.data, net_message.cursize, 1, cls.demofile);
|
||||
if (r != 1)
|
||||
{
|
||||
CL_StopPlayback ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_GetMessage
|
||||
|
||||
Handles recording and playback of demos, on top of NET_ code
|
||||
====================
|
||||
*/
|
||||
int CL_GetMessage (void)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (cls.demoplayback)
|
||||
return CL_GetDemoMessage ();
|
||||
|
||||
while (1)
|
||||
{
|
||||
r = NET_GetMessage (cls.netcon);
|
||||
|
||||
if (r != 1 && r != 2)
|
||||
return r;
|
||||
|
||||
// discard nop keepalive message
|
||||
if (net_message.cursize == 1 && net_message.data[0] == svc_nop)
|
||||
Con_Printf ("<-- server to client keepalive\n");
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (cls.demorecording)
|
||||
CL_WriteDemoMessage ();
|
||||
|
||||
if (cls.signon < 2)
|
||||
{
|
||||
// record messages before full connection, so that a
|
||||
// demo record can happen after connection is done
|
||||
Vec_Append ((void**)&demo_head, 1, net_message.data, net_message.cursize);
|
||||
VEC_PUSH (demo_head_sizes, net_message.cursize);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_Stop_f
|
||||
|
||||
stop recording a demo
|
||||
====================
|
||||
*/
|
||||
void CL_Stop_f (void)
|
||||
{
|
||||
if (cmd_source != src_command)
|
||||
return;
|
||||
|
||||
if (!cls.demorecording)
|
||||
{
|
||||
Con_Printf ("Not recording a demo.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// write a disconnect message to the demo file
|
||||
SZ_Clear (&net_message);
|
||||
MSG_WriteByte (&net_message, svc_disconnect);
|
||||
CL_WriteDemoMessage ();
|
||||
|
||||
// finish up
|
||||
fclose (cls.demofile);
|
||||
cls.demofile = NULL;
|
||||
cls.demorecording = false;
|
||||
Con_Printf ("Completed demo\n");
|
||||
|
||||
// ericw -- update demo tab-completion list
|
||||
DemoList_Rebuild ();
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_Record_f
|
||||
|
||||
record <demoname> <map> [cd track]
|
||||
====================
|
||||
*/
|
||||
void CL_Record_f (void)
|
||||
{
|
||||
int c;
|
||||
char name[MAX_OSPATH];
|
||||
int track;
|
||||
|
||||
if (cmd_source != src_command)
|
||||
return;
|
||||
|
||||
if (cls.demoplayback)
|
||||
{
|
||||
Con_Printf ("Can't record during demo playback\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cls.demorecording)
|
||||
CL_Stop_f();
|
||||
|
||||
c = Cmd_Argc();
|
||||
if (c != 2 && c != 3 && c != 4)
|
||||
{
|
||||
Con_Printf ("record <demoname> [<map> [cd track]]\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strstr(Cmd_Argv(1), ".."))
|
||||
{
|
||||
Con_Printf ("Relative pathnames are not allowed.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (c == 2 && cls.state == ca_connected)
|
||||
{
|
||||
#if 0
|
||||
Con_Printf("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
|
||||
return;
|
||||
#endif
|
||||
if (cls.signon < 2)
|
||||
{
|
||||
Con_Printf("Can't record - try again when connected\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// write the forced cd track number, or -1
|
||||
if (c == 4)
|
||||
{
|
||||
track = atoi(Cmd_Argv(3));
|
||||
Con_Printf ("Forcing CD track to %i\n", cls.forcetrack);
|
||||
}
|
||||
else
|
||||
{
|
||||
track = -1;
|
||||
}
|
||||
|
||||
q_snprintf (name, sizeof(name), "%s/%s", com_gamedir, Cmd_Argv(1));
|
||||
|
||||
// start the map up
|
||||
if (c > 2)
|
||||
{
|
||||
Cmd_ExecuteString ( va("map %s", Cmd_Argv(2)), src_command);
|
||||
if (cls.state != ca_connected)
|
||||
return;
|
||||
}
|
||||
|
||||
// open the demo file
|
||||
COM_AddExtension (name, ".dem", sizeof(name));
|
||||
|
||||
Con_Printf ("recording to %s.\n", name);
|
||||
cls.demofile = fopen (name, "wb");
|
||||
if (!cls.demofile)
|
||||
{
|
||||
Con_Printf ("ERROR: couldn't create %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
cls.forcetrack = track;
|
||||
fprintf (cls.demofile, "%i\n", cls.forcetrack);
|
||||
|
||||
cls.demorecording = true;
|
||||
|
||||
// from ProQuake: initialize the demo file if we're already connected
|
||||
if (c == 2 && cls.state == ca_connected)
|
||||
{
|
||||
static byte tmpbuf[NET_MAXMESSAGE];
|
||||
byte *data = net_message.data;
|
||||
int cursize = net_message.cursize;
|
||||
int maxsize = net_message.maxsize;
|
||||
int i, count;
|
||||
|
||||
net_message.data = demo_head;
|
||||
for (i = 0, count = VEC_SIZE (demo_head_sizes); i < count; i++)
|
||||
{
|
||||
net_message.cursize = demo_head_sizes[i];
|
||||
CL_WriteDemoMessage ();
|
||||
net_message.data += net_message.cursize;
|
||||
}
|
||||
|
||||
net_message.data = tmpbuf;
|
||||
net_message.maxsize = sizeof (tmpbuf);
|
||||
SZ_Clear (&net_message);
|
||||
|
||||
// current names, colors, and frag counts
|
||||
for (i = 0; i < cl.maxclients; i++)
|
||||
{
|
||||
MSG_WriteByte (&net_message, svc_updatename);
|
||||
MSG_WriteByte (&net_message, i);
|
||||
MSG_WriteString (&net_message, cl.scores[i].name);
|
||||
MSG_WriteByte (&net_message, svc_updatefrags);
|
||||
MSG_WriteByte (&net_message, i);
|
||||
MSG_WriteShort (&net_message, cl.scores[i].frags);
|
||||
MSG_WriteByte (&net_message, svc_updatecolors);
|
||||
MSG_WriteByte (&net_message, i);
|
||||
MSG_WriteByte (&net_message, cl.scores[i].colors);
|
||||
}
|
||||
|
||||
// send all current light styles
|
||||
for (i = 0; i < MAX_LIGHTSTYLES; i++)
|
||||
{
|
||||
MSG_WriteByte (&net_message, svc_lightstyle);
|
||||
MSG_WriteByte (&net_message, i);
|
||||
MSG_WriteString (&net_message, cl_lightstyle[i].map);
|
||||
}
|
||||
|
||||
// what about the CD track or SVC fog... future consideration.
|
||||
MSG_WriteByte (&net_message, svc_updatestat);
|
||||
MSG_WriteByte (&net_message, STAT_TOTALSECRETS);
|
||||
MSG_WriteLong (&net_message, cl.stats[STAT_TOTALSECRETS]);
|
||||
|
||||
MSG_WriteByte (&net_message, svc_updatestat);
|
||||
MSG_WriteByte (&net_message, STAT_TOTALMONSTERS);
|
||||
MSG_WriteLong (&net_message, cl.stats[STAT_TOTALMONSTERS]);
|
||||
|
||||
MSG_WriteByte (&net_message, svc_updatestat);
|
||||
MSG_WriteByte (&net_message, STAT_SECRETS);
|
||||
MSG_WriteLong (&net_message, cl.stats[STAT_SECRETS]);
|
||||
|
||||
MSG_WriteByte (&net_message, svc_updatestat);
|
||||
MSG_WriteByte (&net_message, STAT_MONSTERS);
|
||||
MSG_WriteLong (&net_message, cl.stats[STAT_MONSTERS]);
|
||||
|
||||
// view entity
|
||||
MSG_WriteByte (&net_message, svc_setview);
|
||||
MSG_WriteShort (&net_message, cl.viewentity);
|
||||
|
||||
// signon
|
||||
MSG_WriteByte (&net_message, svc_signonnum);
|
||||
MSG_WriteByte (&net_message, 3);
|
||||
|
||||
CL_WriteDemoMessage();
|
||||
|
||||
// restore net_message
|
||||
net_message.data = data;
|
||||
net_message.cursize = cursize;
|
||||
net_message.maxsize = maxsize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_PlayDemo_f
|
||||
|
||||
play [demoname]
|
||||
====================
|
||||
*/
|
||||
void CL_PlayDemo_f (void)
|
||||
{
|
||||
char name[MAX_OSPATH];
|
||||
|
||||
if (cmd_source != src_command)
|
||||
return;
|
||||
|
||||
if (Cmd_Argc() != 2)
|
||||
{
|
||||
Con_Printf ("playdemo <demoname> : plays a demo\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// disconnect from server
|
||||
CL_Disconnect ();
|
||||
|
||||
// open the demo file
|
||||
std::strncpy(name, Cmd_Argv(1), sizeof(name));
|
||||
COM_AddExtension (name, ".dem", sizeof(name));
|
||||
|
||||
Con_Printf ("Playing demo from %s.\n", name);
|
||||
|
||||
COM_FOpenFile (name, &cls.demofile, NULL);
|
||||
if (!cls.demofile)
|
||||
{
|
||||
Con_Printf ("ERROR: couldn't open %s\n", name);
|
||||
cls.demonum = -1; // stop demo loop
|
||||
return;
|
||||
}
|
||||
|
||||
// ZOID, fscanf is evil
|
||||
// O.S.: if a space character e.g. 0x20 (' ') follows '\n',
|
||||
// fscanf skips that byte too and screws up further reads.
|
||||
// fscanf (cls.demofile, "%i\n", &cls.forcetrack);
|
||||
if (fscanf (cls.demofile, "%i", &cls.forcetrack) != 1 || fgetc (cls.demofile) != '\n')
|
||||
{
|
||||
fclose (cls.demofile);
|
||||
cls.demofile = NULL;
|
||||
cls.demonum = -1; // stop demo loop
|
||||
Con_Printf ("ERROR: demo \"%s\" is invalid\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
cls.demoplayback = true;
|
||||
cls.demopaused = false;
|
||||
cls.state = ca_connected;
|
||||
|
||||
// get rid of the menu and/or console
|
||||
key_dest = key_game;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_FinishTimeDemo
|
||||
|
||||
====================
|
||||
*/
|
||||
static void CL_FinishTimeDemo (void)
|
||||
{
|
||||
int frames;
|
||||
float time;
|
||||
|
||||
cls.timedemo = false;
|
||||
|
||||
// the first frame didn't count
|
||||
frames = (host_framecount - cls.td_startframe) - 1;
|
||||
time = realtime - cls.td_starttime;
|
||||
if (!time)
|
||||
time = 1;
|
||||
Con_Printf ("%i frames %5.1f seconds %5.1f fps\n", frames, time, frames/time);
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_TimeDemo_f
|
||||
|
||||
timedemo [demoname]
|
||||
====================
|
||||
*/
|
||||
void CL_TimeDemo_f (void)
|
||||
{
|
||||
if (cmd_source != src_command)
|
||||
return;
|
||||
|
||||
if (Cmd_Argc() != 2)
|
||||
{
|
||||
Con_Printf ("timedemo <demoname> : gets demo speeds\n");
|
||||
return;
|
||||
}
|
||||
|
||||
CL_PlayDemo_f ();
|
||||
if (!cls.demofile)
|
||||
return;
|
||||
|
||||
// cls.td_starttime will be grabbed at the second frame of the demo, so
|
||||
// all the loading time doesn't get counted
|
||||
|
||||
cls.timedemo = true;
|
||||
cls.td_startframe = host_framecount;
|
||||
cls.td_lastframe = -1; // get a new message this frame
|
||||
}
|
||||
|
||||
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// cl.input.c -- builds an intended movement command to send to the server
|
||||
|
||||
// Quake is a trademark of Id Software, Inc., (c) 1996 Id Software, Inc. All
|
||||
// rights reserved.
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
extern cvar_t cl_maxpitch; //johnfitz -- variable pitch clamping
|
||||
extern cvar_t cl_minpitch; //johnfitz -- variable pitch clamping
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
KEY BUTTONS
|
||||
|
||||
Continuous button event tracking is complicated by the fact that two different
|
||||
input sources (say, mouse button 1 and the control key) can both press the
|
||||
same button, but the button should only be released when both of the
|
||||
pressing key have been released.
|
||||
|
||||
When a key event issues a button command (+forward, +attack, etc), it appends
|
||||
its key number as a parameter to the command so it can be matched up with
|
||||
the release.
|
||||
|
||||
state bit 0 is the current state of the key
|
||||
state bit 1 is edge triggered on the up to down transition
|
||||
state bit 2 is edge triggered on the down to up transition
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
|
||||
kbutton_t in_mlook, in_klook;
|
||||
kbutton_t in_left, in_right, in_forward, in_back;
|
||||
kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright;
|
||||
kbutton_t in_strafe, in_speed, in_use, in_jump, in_attack;
|
||||
kbutton_t in_up, in_down;
|
||||
|
||||
int in_impulse;
|
||||
|
||||
|
||||
void KeyDown (kbutton_t *b)
|
||||
{
|
||||
int k;
|
||||
const char *c;
|
||||
|
||||
c = Cmd_Argv(1);
|
||||
if (c[0])
|
||||
k = atoi(c);
|
||||
else
|
||||
k = -1; // typed manually at the console for continuous down
|
||||
|
||||
if (k == b->down[0] || k == b->down[1])
|
||||
return; // repeating key
|
||||
|
||||
if (!b->down[0])
|
||||
b->down[0] = k;
|
||||
else if (!b->down[1])
|
||||
b->down[1] = k;
|
||||
else
|
||||
{
|
||||
Con_Printf ("Three keys down for a button!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (b->state & 1)
|
||||
return; // still down
|
||||
b->state |= 1 + 2; // down + impulse down
|
||||
}
|
||||
|
||||
void KeyUp (kbutton_t *b)
|
||||
{
|
||||
int k;
|
||||
const char *c;
|
||||
|
||||
c = Cmd_Argv(1);
|
||||
if (c[0])
|
||||
k = atoi(c);
|
||||
else
|
||||
{ // typed manually at the console, assume for unsticking, so clear all
|
||||
b->down[0] = b->down[1] = 0;
|
||||
b->state = 4; // impulse up
|
||||
return;
|
||||
}
|
||||
|
||||
if (b->down[0] == k)
|
||||
b->down[0] = 0;
|
||||
else if (b->down[1] == k)
|
||||
b->down[1] = 0;
|
||||
else
|
||||
return; // key up without coresponding down (menu pass through)
|
||||
if (b->down[0] || b->down[1])
|
||||
return; // some other key is still holding it down
|
||||
|
||||
if (!(b->state & 1))
|
||||
return; // still up (this should not happen)
|
||||
b->state &= ~1; // now up
|
||||
b->state |= 4; // impulse up
|
||||
}
|
||||
|
||||
void IN_KLookDown (void) {KeyDown(&in_klook);}
|
||||
void IN_KLookUp (void) {KeyUp(&in_klook);}
|
||||
void IN_MLookDown (void) {KeyDown(&in_mlook);}
|
||||
void IN_MLookUp (void) {
|
||||
KeyUp(&in_mlook);
|
||||
if ( !(in_mlook.state&1) && lookspring.value)
|
||||
V_StartPitchDrift();
|
||||
}
|
||||
void IN_UpDown(void) {KeyDown(&in_up);}
|
||||
void IN_UpUp(void) {KeyUp(&in_up);}
|
||||
void IN_DownDown(void) {KeyDown(&in_down);}
|
||||
void IN_DownUp(void) {KeyUp(&in_down);}
|
||||
void IN_LeftDown(void) {KeyDown(&in_left);}
|
||||
void IN_LeftUp(void) {KeyUp(&in_left);}
|
||||
void IN_RightDown(void) {KeyDown(&in_right);}
|
||||
void IN_RightUp(void) {KeyUp(&in_right);}
|
||||
void IN_ForwardDown(void) {KeyDown(&in_forward);}
|
||||
void IN_ForwardUp(void) {KeyUp(&in_forward);}
|
||||
void IN_BackDown(void) {KeyDown(&in_back);}
|
||||
void IN_BackUp(void) {KeyUp(&in_back);}
|
||||
void IN_LookupDown(void) {KeyDown(&in_lookup);}
|
||||
void IN_LookupUp(void) {KeyUp(&in_lookup);}
|
||||
void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
|
||||
void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
|
||||
void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
|
||||
void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
|
||||
void IN_MoverightDown(void) {KeyDown(&in_moveright);}
|
||||
void IN_MoverightUp(void) {KeyUp(&in_moveright);}
|
||||
|
||||
void IN_SpeedDown(void) {KeyDown(&in_speed);}
|
||||
void IN_SpeedUp(void) {KeyUp(&in_speed);}
|
||||
void IN_StrafeDown(void) {KeyDown(&in_strafe);}
|
||||
void IN_StrafeUp(void) {KeyUp(&in_strafe);}
|
||||
|
||||
void IN_AttackDown(void) {KeyDown(&in_attack);}
|
||||
void IN_AttackUp(void) {KeyUp(&in_attack);}
|
||||
|
||||
void IN_UseDown (void) {KeyDown(&in_use);}
|
||||
void IN_UseUp (void) {KeyUp(&in_use);}
|
||||
void IN_JumpDown (void) {KeyDown(&in_jump);}
|
||||
void IN_JumpUp (void) {KeyUp(&in_jump);}
|
||||
|
||||
void IN_Impulse (void) {in_impulse=Q_atoi(Cmd_Argv(1));}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_KeyState
|
||||
|
||||
Returns 0.25 if a key was pressed and released during the frame,
|
||||
0.5 if it was pressed and held
|
||||
0 if held then released, and
|
||||
1.0 if held for the entire time
|
||||
===============
|
||||
*/
|
||||
float CL_KeyState (kbutton_t *key)
|
||||
{
|
||||
float val;
|
||||
qboolean impulsedown, impulseup, down;
|
||||
|
||||
impulsedown = key->state & 2;
|
||||
impulseup = key->state & 4;
|
||||
down = key->state & 1;
|
||||
val = 0;
|
||||
|
||||
if (impulsedown && !impulseup)
|
||||
{
|
||||
if (down)
|
||||
val = 0.5; // pressed and held this frame
|
||||
else
|
||||
val = 0; // I_Error ();
|
||||
}
|
||||
if (impulseup && !impulsedown)
|
||||
{
|
||||
if (down)
|
||||
val = 0; // I_Error ();
|
||||
else
|
||||
val = 0; // released this frame
|
||||
}
|
||||
if (!impulsedown && !impulseup)
|
||||
{
|
||||
if (down)
|
||||
val = 1.0; // held the entire frame
|
||||
else
|
||||
val = 0; // up the entire frame
|
||||
}
|
||||
if (impulsedown && impulseup)
|
||||
{
|
||||
if (down)
|
||||
val = 0.75; // released and re-pressed this frame
|
||||
else
|
||||
val = 0.25; // pressed and released this frame
|
||||
}
|
||||
|
||||
key->state &= 1; // clear impulses
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
||||
cvar_t cl_upspeed = {"cl_upspeed","200",CVAR_NONE};
|
||||
cvar_t cl_forwardspeed = {"cl_forwardspeed","200", CVAR_ARCHIVE};
|
||||
cvar_t cl_backspeed = {"cl_backspeed","200", CVAR_ARCHIVE};
|
||||
cvar_t cl_sidespeed = {"cl_sidespeed","350",CVAR_NONE};
|
||||
|
||||
cvar_t cl_movespeedkey = {"cl_movespeedkey","2.0",CVAR_NONE};
|
||||
|
||||
cvar_t cl_yawspeed = {"cl_yawspeed","140",CVAR_NONE};
|
||||
cvar_t cl_pitchspeed = {"cl_pitchspeed","150",CVAR_NONE};
|
||||
|
||||
cvar_t cl_anglespeedkey = {"cl_anglespeedkey","1.5",CVAR_NONE};
|
||||
|
||||
cvar_t cl_alwaysrun = {"cl_alwaysrun","0",CVAR_ARCHIVE}; // QuakeSpasm -- new always run
|
||||
|
||||
/*
|
||||
================
|
||||
CL_AdjustAngles
|
||||
|
||||
Moves the local angle positions
|
||||
================
|
||||
*/
|
||||
void CL_AdjustAngles (void)
|
||||
{
|
||||
float speed;
|
||||
float up, down;
|
||||
|
||||
if ((in_speed.state & 1) ^ (cl_alwaysrun.value != 0.0))
|
||||
speed = host_frametime * cl_anglespeedkey.value;
|
||||
else
|
||||
speed = host_frametime;
|
||||
|
||||
if (!(in_strafe.state & 1))
|
||||
{
|
||||
cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right);
|
||||
cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left);
|
||||
cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
|
||||
}
|
||||
if (in_klook.state & 1)
|
||||
{
|
||||
V_StopPitchDrift ();
|
||||
cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward);
|
||||
cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back);
|
||||
}
|
||||
|
||||
up = CL_KeyState (&in_lookup);
|
||||
down = CL_KeyState(&in_lookdown);
|
||||
|
||||
cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up;
|
||||
cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down;
|
||||
|
||||
if (up || down)
|
||||
V_StopPitchDrift ();
|
||||
|
||||
//johnfitz -- variable pitch clamping
|
||||
if (cl.viewangles[PITCH] > cl_maxpitch.value)
|
||||
cl.viewangles[PITCH] = cl_maxpitch.value;
|
||||
if (cl.viewangles[PITCH] < cl_minpitch.value)
|
||||
cl.viewangles[PITCH] = cl_minpitch.value;
|
||||
//johnfitz
|
||||
|
||||
if (cl.viewangles[ROLL] > 50)
|
||||
cl.viewangles[ROLL] = 50;
|
||||
if (cl.viewangles[ROLL] < -50)
|
||||
cl.viewangles[ROLL] = -50;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_BaseMove
|
||||
|
||||
Send the intended movement message to the server
|
||||
================
|
||||
*/
|
||||
void CL_BaseMove (usercmd_t *cmd)
|
||||
{
|
||||
if (cls.signon != SIGNONS)
|
||||
return;
|
||||
|
||||
CL_AdjustAngles ();
|
||||
|
||||
Q_memset (cmd, 0, sizeof(*cmd));
|
||||
|
||||
if (in_strafe.state & 1)
|
||||
{
|
||||
cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
|
||||
cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
|
||||
}
|
||||
|
||||
cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
|
||||
cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
|
||||
|
||||
cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
|
||||
cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);
|
||||
|
||||
if (! (in_klook.state & 1) )
|
||||
{
|
||||
cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
|
||||
cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
|
||||
}
|
||||
|
||||
//
|
||||
// adjust for speed key
|
||||
//
|
||||
if ((in_speed.state & 1) ^ (cl_alwaysrun.value != 0.0))
|
||||
{
|
||||
cmd->forwardmove *= cl_movespeedkey.value;
|
||||
cmd->sidemove *= cl_movespeedkey.value;
|
||||
cmd->upmove *= cl_movespeedkey.value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_SendMove
|
||||
==============
|
||||
*/
|
||||
void CL_SendMove (const usercmd_t *cmd)
|
||||
{
|
||||
int i;
|
||||
int bits;
|
||||
sizebuf_t buf;
|
||||
byte data[128];
|
||||
|
||||
buf.maxsize = 128;
|
||||
buf.cursize = 0;
|
||||
buf.data = data;
|
||||
|
||||
cl.cmd = *cmd;
|
||||
|
||||
//
|
||||
// send the movement message
|
||||
//
|
||||
MSG_WriteByte (&buf, clc_move);
|
||||
|
||||
MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
//johnfitz -- 16-bit angles for PROTOCOL_FITZQUAKE
|
||||
if (cl.protocol == PROTOCOL_NETQUAKE)
|
||||
MSG_WriteAngle (&buf, cl.viewangles[i], cl.protocolflags);
|
||||
else
|
||||
MSG_WriteAngle16 (&buf, cl.viewangles[i], cl.protocolflags);
|
||||
//johnfitz
|
||||
|
||||
MSG_WriteShort (&buf, cmd->forwardmove);
|
||||
MSG_WriteShort (&buf, cmd->sidemove);
|
||||
MSG_WriteShort (&buf, cmd->upmove);
|
||||
|
||||
//
|
||||
// send button bits
|
||||
//
|
||||
bits = 0;
|
||||
|
||||
if ( in_attack.state & 3 )
|
||||
bits |= 1;
|
||||
in_attack.state &= ~2;
|
||||
|
||||
if (in_jump.state & 3)
|
||||
bits |= 2;
|
||||
in_jump.state &= ~2;
|
||||
|
||||
MSG_WriteByte (&buf, bits);
|
||||
|
||||
MSG_WriteByte (&buf, in_impulse);
|
||||
in_impulse = 0;
|
||||
|
||||
//
|
||||
// deliver the message
|
||||
//
|
||||
if (cls.demoplayback)
|
||||
return;
|
||||
|
||||
//
|
||||
// allways dump the first two message, because it may contain leftover inputs
|
||||
// from the last level
|
||||
//
|
||||
if (++cl.movemessages <= 2)
|
||||
return;
|
||||
|
||||
if (NET_SendUnreliableMessage (cls.netcon, &buf) == -1)
|
||||
{
|
||||
Con_Printf ("CL_SendMove: lost server connection\n");
|
||||
CL_Disconnect ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
CL_InitInput
|
||||
============
|
||||
*/
|
||||
void CL_InitInput (void)
|
||||
{
|
||||
Cmd_AddCommand ("+moveup",IN_UpDown);
|
||||
Cmd_AddCommand ("-moveup",IN_UpUp);
|
||||
Cmd_AddCommand ("+movedown",IN_DownDown);
|
||||
Cmd_AddCommand ("-movedown",IN_DownUp);
|
||||
Cmd_AddCommand ("+left",IN_LeftDown);
|
||||
Cmd_AddCommand ("-left",IN_LeftUp);
|
||||
Cmd_AddCommand ("+right",IN_RightDown);
|
||||
Cmd_AddCommand ("-right",IN_RightUp);
|
||||
Cmd_AddCommand ("+forward",IN_ForwardDown);
|
||||
Cmd_AddCommand ("-forward",IN_ForwardUp);
|
||||
Cmd_AddCommand ("+back",IN_BackDown);
|
||||
Cmd_AddCommand ("-back",IN_BackUp);
|
||||
Cmd_AddCommand ("+lookup", IN_LookupDown);
|
||||
Cmd_AddCommand ("-lookup", IN_LookupUp);
|
||||
Cmd_AddCommand ("+lookdown", IN_LookdownDown);
|
||||
Cmd_AddCommand ("-lookdown", IN_LookdownUp);
|
||||
Cmd_AddCommand ("+strafe", IN_StrafeDown);
|
||||
Cmd_AddCommand ("-strafe", IN_StrafeUp);
|
||||
Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
|
||||
Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
|
||||
Cmd_AddCommand ("+moveright", IN_MoverightDown);
|
||||
Cmd_AddCommand ("-moveright", IN_MoverightUp);
|
||||
Cmd_AddCommand ("+speed", IN_SpeedDown);
|
||||
Cmd_AddCommand ("-speed", IN_SpeedUp);
|
||||
Cmd_AddCommand ("+attack", IN_AttackDown);
|
||||
Cmd_AddCommand ("-attack", IN_AttackUp);
|
||||
Cmd_AddCommand ("+use", IN_UseDown);
|
||||
Cmd_AddCommand ("-use", IN_UseUp);
|
||||
Cmd_AddCommand ("+jump", IN_JumpDown);
|
||||
Cmd_AddCommand ("-jump", IN_JumpUp);
|
||||
Cmd_AddCommand ("impulse", IN_Impulse);
|
||||
Cmd_AddCommand ("+klook", IN_KLookDown);
|
||||
Cmd_AddCommand ("-klook", IN_KLookUp);
|
||||
Cmd_AddCommand ("+mlook", IN_MLookDown);
|
||||
Cmd_AddCommand ("-mlook", IN_MLookUp);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,841 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// cl_main.c -- client main loop
|
||||
|
||||
#include "quakedef.hpp"
|
||||
#include "bgmusic.hpp"
|
||||
|
||||
// we need to declare some mouse variables here, because the menu system
|
||||
// references them even when on a unix system.
|
||||
|
||||
// these two are not intended to be set directly
|
||||
cvar_t cl_name = {"_cl_name", "player", CVAR_ARCHIVE};
|
||||
cvar_t cl_color = {"_cl_color", "0", CVAR_ARCHIVE};
|
||||
|
||||
cvar_t cl_shownet = {"cl_shownet","0",CVAR_NONE}; // can be 0, 1, or 2
|
||||
cvar_t cl_nolerp = {"cl_nolerp","0",CVAR_NONE};
|
||||
|
||||
cvar_t cfg_unbindall = {"cfg_unbindall", "1", CVAR_ARCHIVE};
|
||||
|
||||
cvar_t lookspring = {"lookspring","0", CVAR_ARCHIVE};
|
||||
cvar_t lookstrafe = {"lookstrafe","0", CVAR_ARCHIVE};
|
||||
cvar_t sensitivity = {"sensitivity","3", CVAR_ARCHIVE};
|
||||
|
||||
cvar_t m_pitch = {"m_pitch","0.022", CVAR_ARCHIVE};
|
||||
cvar_t m_yaw = {"m_yaw","0.022", CVAR_ARCHIVE};
|
||||
cvar_t m_forward = {"m_forward","1", CVAR_ARCHIVE};
|
||||
cvar_t m_side = {"m_side","0.8", CVAR_ARCHIVE};
|
||||
|
||||
cvar_t cl_maxpitch = {"cl_maxpitch", "90", CVAR_ARCHIVE}; //johnfitz -- variable pitch clamping
|
||||
cvar_t cl_minpitch = {"cl_minpitch", "-90", CVAR_ARCHIVE}; //johnfitz -- variable pitch clamping
|
||||
|
||||
cvar_t cl_startdemos = {"cl_startdemos", "1", CVAR_ARCHIVE};
|
||||
|
||||
client_static_t cls;
|
||||
client_state_t cl;
|
||||
// FIXME: put these on hunk?
|
||||
entity_t cl_static_entities[MAX_STATIC_ENTITIES];
|
||||
lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
|
||||
dlight_t cl_dlights[MAX_DLIGHTS];
|
||||
|
||||
entity_t *cl_entities; //johnfitz -- was a static array, now on hunk
|
||||
int cl_max_edicts; //johnfitz -- only changes when new map loads
|
||||
|
||||
int cl_numvisedicts;
|
||||
entity_t *cl_visedicts[MAX_VISEDICTS];
|
||||
|
||||
extern cvar_t r_lerpmodels, r_lerpmove; //johnfitz
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_ClearState
|
||||
|
||||
=====================
|
||||
*/
|
||||
void CL_ClearState (void)
|
||||
{
|
||||
if (!sv.active)
|
||||
Host_ClearMemory ();
|
||||
|
||||
// wipe the entire cl structure
|
||||
memset (&cl, 0, sizeof(cl));
|
||||
|
||||
SZ_Clear (&cls.message);
|
||||
|
||||
// clear other arrays
|
||||
memset (cl_dlights, 0, sizeof(cl_dlights));
|
||||
memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
|
||||
memset (cl_temp_entities, 0, sizeof(cl_temp_entities));
|
||||
memset (cl_beams, 0, sizeof(cl_beams));
|
||||
|
||||
//johnfitz -- cl_entities is now dynamically allocated
|
||||
cl_max_edicts = CLAMP (MIN_EDICTS,(int)max_edicts.value,MAX_EDICTS);
|
||||
cl_entities = (entity_t *) Hunk_AllocName (cl_max_edicts*sizeof(entity_t), "cl_entities");
|
||||
//johnfitz
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_Disconnect
|
||||
|
||||
Sends a disconnect message to the server
|
||||
This is also called on Host_Error, so it shouldn't cause any errors
|
||||
=====================
|
||||
*/
|
||||
void CL_Disconnect (void)
|
||||
{
|
||||
if (key_dest == key_message)
|
||||
Key_EndChat (); // don't get stuck in chat mode
|
||||
|
||||
// stop sounds (especially looping!)
|
||||
S_StopAllSounds (true);
|
||||
BGM_Stop();
|
||||
CDAudio_Stop();
|
||||
|
||||
// if running a local server, shut it down
|
||||
if (cls.demoplayback)
|
||||
CL_StopPlayback ();
|
||||
else if (cls.state == ca_connected)
|
||||
{
|
||||
if (cls.demorecording)
|
||||
CL_Stop_f ();
|
||||
|
||||
Con_DPrintf ("Sending clc_disconnect\n");
|
||||
SZ_Clear (&cls.message);
|
||||
MSG_WriteByte (&cls.message, clc_disconnect);
|
||||
NET_SendUnreliableMessage (cls.netcon, &cls.message);
|
||||
SZ_Clear (&cls.message);
|
||||
NET_Close (cls.netcon);
|
||||
|
||||
cls.state = ca_disconnected;
|
||||
if (sv.active)
|
||||
Host_ShutdownServer(false);
|
||||
}
|
||||
|
||||
cls.demoplayback = cls.timedemo = false;
|
||||
cls.demopaused = false;
|
||||
cl.intermission = 0;
|
||||
CL_ClearSignons ();
|
||||
}
|
||||
|
||||
void CL_Disconnect_f (void)
|
||||
{
|
||||
CL_Disconnect ();
|
||||
if (sv.active)
|
||||
Host_ShutdownServer (false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_EstablishConnection
|
||||
|
||||
Host should be either "local" or a net address to be passed on
|
||||
=====================
|
||||
*/
|
||||
void CL_EstablishConnection (const char *host)
|
||||
{
|
||||
if (cls.state == ca_dedicated)
|
||||
return;
|
||||
|
||||
if (cls.demoplayback)
|
||||
return;
|
||||
|
||||
CL_Disconnect ();
|
||||
|
||||
cls.netcon = NET_Connect (host);
|
||||
if (!cls.netcon)
|
||||
Host_Error ("CL_Connect: connect failed");
|
||||
Con_DPrintf ("CL_EstablishConnection: connected to %s\n", host);
|
||||
|
||||
cls.demonum = -1; // not in the demo loop now
|
||||
cls.state = ca_connected;
|
||||
CL_ClearSignons (); // need all the signon messages before playing
|
||||
MSG_WriteByte (&cls.message, clc_nop); // NAT Fix from ProQuake
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_SignonReply
|
||||
|
||||
An svc_signonnum has been received, perform a client side setup
|
||||
=====================
|
||||
*/
|
||||
void CL_SignonReply (void)
|
||||
{
|
||||
char str[8192];
|
||||
|
||||
Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
|
||||
|
||||
switch (cls.signon)
|
||||
{
|
||||
case 1:
|
||||
MSG_WriteByte (&cls.message, clc_stringcmd);
|
||||
MSG_WriteString (&cls.message, "prespawn");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
MSG_WriteByte (&cls.message, clc_stringcmd);
|
||||
MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
|
||||
|
||||
MSG_WriteByte (&cls.message, clc_stringcmd);
|
||||
MSG_WriteString (&cls.message, va("color %i %i\n", ((int)cl_color.value)>>4, ((int)cl_color.value)&15));
|
||||
|
||||
MSG_WriteByte (&cls.message, clc_stringcmd);
|
||||
sprintf (str, "spawn %s", cls.spawnparms);
|
||||
MSG_WriteString (&cls.message, str);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
MSG_WriteByte (&cls.message, clc_stringcmd);
|
||||
MSG_WriteString (&cls.message, "begin");
|
||||
Cache_Report (); // print remaining memory
|
||||
break;
|
||||
|
||||
case 4:
|
||||
SCR_EndLoadingPlaque (); // allow normal screen updates
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_NextDemo
|
||||
|
||||
Called to play the next demo in the demo loop
|
||||
=====================
|
||||
*/
|
||||
void CL_NextDemo (void)
|
||||
{
|
||||
char str[1024];
|
||||
|
||||
if (cls.demonum == -1)
|
||||
return; // don't play demos
|
||||
|
||||
if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS)
|
||||
{
|
||||
cls.demonum = 0;
|
||||
if (!cls.demos[cls.demonum][0])
|
||||
{
|
||||
Con_Printf ("No demos listed with startdemos\n");
|
||||
cls.demonum = -1;
|
||||
CL_Disconnect();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SCR_BeginLoadingPlaque ();
|
||||
|
||||
sprintf (str,"playdemo %s\n", cls.demos[cls.demonum]);
|
||||
Cbuf_InsertText (str);
|
||||
cls.demonum++;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_PrintEntities_f
|
||||
==============
|
||||
*/
|
||||
void CL_PrintEntities_f (void)
|
||||
{
|
||||
entity_t *ent;
|
||||
int i;
|
||||
|
||||
if (cls.state != ca_connected)
|
||||
return;
|
||||
|
||||
for (i=0,ent=cl_entities ; i<cl.num_entities ; i++,ent++)
|
||||
{
|
||||
Con_Printf ("%3i:",i);
|
||||
if (!ent->model)
|
||||
{
|
||||
Con_Printf ("EMPTY\n");
|
||||
continue;
|
||||
}
|
||||
Con_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n"
|
||||
,ent->model->name,ent->frame, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_AllocDlight
|
||||
|
||||
===============
|
||||
*/
|
||||
dlight_t *CL_AllocDlight (int key)
|
||||
{
|
||||
int i;
|
||||
dlight_t *dl;
|
||||
|
||||
// first look for an exact key match
|
||||
if (key)
|
||||
{
|
||||
dl = cl_dlights;
|
||||
for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
|
||||
{
|
||||
if (dl->key == key)
|
||||
{
|
||||
memset (dl, 0, sizeof(*dl));
|
||||
dl->key = key;
|
||||
dl->color[0] = dl->color[1] = dl->color[2] = 1; //johnfitz -- lit support via lordhavoc
|
||||
return dl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// then look for anything else
|
||||
dl = cl_dlights;
|
||||
for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
|
||||
{
|
||||
if (dl->die < cl.time)
|
||||
{
|
||||
memset (dl, 0, sizeof(*dl));
|
||||
dl->key = key;
|
||||
dl->color[0] = dl->color[1] = dl->color[2] = 1; //johnfitz -- lit support via lordhavoc
|
||||
return dl;
|
||||
}
|
||||
}
|
||||
|
||||
dl = &cl_dlights[0];
|
||||
memset (dl, 0, sizeof(*dl));
|
||||
dl->key = key;
|
||||
dl->color[0] = dl->color[1] = dl->color[2] = 1; //johnfitz -- lit support via lordhavoc
|
||||
return dl;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_DecayLights
|
||||
|
||||
===============
|
||||
*/
|
||||
void CL_DecayLights (void)
|
||||
{
|
||||
int i;
|
||||
dlight_t *dl;
|
||||
float time;
|
||||
|
||||
time = cl.time - cl.oldtime;
|
||||
|
||||
dl = cl_dlights;
|
||||
for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
|
||||
{
|
||||
if (dl->die < cl.time || !dl->radius)
|
||||
continue;
|
||||
|
||||
dl->radius -= time*dl->decay;
|
||||
if (dl->radius < 0)
|
||||
dl->radius = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_LerpPoint
|
||||
|
||||
Determines the fraction between the last two messages that the objects
|
||||
should be put at.
|
||||
===============
|
||||
*/
|
||||
float CL_LerpPoint (void)
|
||||
{
|
||||
float f, frac;
|
||||
|
||||
f = cl.mtime[0] - cl.mtime[1];
|
||||
|
||||
if (!f || cls.timedemo || sv.active)
|
||||
{
|
||||
cl.time = cl.mtime[0];
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (f > 0.1) // dropped packet, or start of demo
|
||||
{
|
||||
cl.mtime[1] = cl.mtime[0] - 0.1;
|
||||
f = 0.1;
|
||||
}
|
||||
|
||||
frac = (cl.time - cl.mtime[1]) / f;
|
||||
|
||||
if (frac < 0)
|
||||
{
|
||||
if (frac < -0.01)
|
||||
cl.time = cl.mtime[1];
|
||||
frac = 0;
|
||||
}
|
||||
else if (frac > 1)
|
||||
{
|
||||
if (frac > 1.01)
|
||||
cl.time = cl.mtime[0];
|
||||
frac = 1;
|
||||
}
|
||||
|
||||
//johnfitz -- better nolerp behavior
|
||||
if (cl_nolerp.value)
|
||||
return 1;
|
||||
//johnfitz
|
||||
|
||||
return frac;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_RelinkEntities
|
||||
===============
|
||||
*/
|
||||
void CL_RelinkEntities (void)
|
||||
{
|
||||
entity_t *ent;
|
||||
int i, j;
|
||||
float frac, f, d;
|
||||
vec3_t delta;
|
||||
float bobjrotate;
|
||||
vec3_t oldorg;
|
||||
dlight_t *dl;
|
||||
|
||||
// determine partial update time
|
||||
frac = CL_LerpPoint ();
|
||||
|
||||
cl_numvisedicts = 0;
|
||||
|
||||
//
|
||||
// interpolate player info
|
||||
//
|
||||
for (i=0 ; i<3 ; i++)
|
||||
cl.velocity[i] = cl.mvelocity[1][i] +
|
||||
frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]);
|
||||
|
||||
if (cls.demoplayback)
|
||||
{
|
||||
// interpolate the angles
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
d = cl.mviewangles[0][j] - cl.mviewangles[1][j];
|
||||
if (d > 180)
|
||||
d -= 360;
|
||||
else if (d < -180)
|
||||
d += 360;
|
||||
cl.viewangles[j] = cl.mviewangles[1][j] + frac*d;
|
||||
}
|
||||
}
|
||||
|
||||
bobjrotate = anglemod(100*cl.time);
|
||||
|
||||
// start on the entity after the world
|
||||
for (i=1,ent=cl_entities+1 ; i<cl.num_entities ; i++,ent++)
|
||||
{
|
||||
if (!ent->model)
|
||||
{ // empty slot
|
||||
|
||||
// ericw -- efrags are only used for static entities in GLQuake
|
||||
// ent can't be static, so this is a no-op.
|
||||
//if (ent->forcelink)
|
||||
// R_RemoveEfrags (ent); // just became empty
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the object wasn't included in the last packet, remove it
|
||||
if (ent->msgtime != cl.mtime[0])
|
||||
{
|
||||
ent->model = NULL;
|
||||
ent->lerpflags |= LERP_RESETMOVE|LERP_RESETANIM; //johnfitz -- next time this entity slot is reused, the lerp will need to be reset
|
||||
continue;
|
||||
}
|
||||
|
||||
VectorCopy (ent->origin, oldorg);
|
||||
|
||||
if (ent->forcelink)
|
||||
{ // the entity was not updated in the last message
|
||||
// so move to the final spot
|
||||
VectorCopy (ent->msg_origins[0], ent->origin);
|
||||
VectorCopy (ent->msg_angles[0], ent->angles);
|
||||
}
|
||||
else
|
||||
{ // if the delta is large, assume a teleport and don't lerp
|
||||
f = frac;
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
delta[j] = ent->msg_origins[0][j] - ent->msg_origins[1][j];
|
||||
if (delta[j] > 100 || delta[j] < -100)
|
||||
{
|
||||
f = 1; // assume a teleportation, not a motion
|
||||
ent->lerpflags |= LERP_RESETMOVE; //johnfitz -- don't lerp teleports
|
||||
}
|
||||
}
|
||||
|
||||
//johnfitz -- don't cl_lerp entities that will be r_lerped
|
||||
if (r_lerpmove.value && (ent->lerpflags & LERP_MOVESTEP))
|
||||
f = 1;
|
||||
//johnfitz
|
||||
|
||||
// interpolate the origin and angles
|
||||
for (j=0 ; j<3 ; j++)
|
||||
{
|
||||
ent->origin[j] = ent->msg_origins[1][j] + f*delta[j];
|
||||
|
||||
d = ent->msg_angles[0][j] - ent->msg_angles[1][j];
|
||||
if (d > 180)
|
||||
d -= 360;
|
||||
else if (d < -180)
|
||||
d += 360;
|
||||
ent->angles[j] = ent->msg_angles[1][j] + f*d;
|
||||
}
|
||||
}
|
||||
|
||||
// rotate binary objects locally
|
||||
if (ent->model->flags & EF_ROTATE)
|
||||
ent->angles[1] = bobjrotate;
|
||||
|
||||
if (ent->effects & EF_BRIGHTFIELD)
|
||||
R_EntityParticles (ent);
|
||||
|
||||
if (ent->effects & EF_MUZZLEFLASH)
|
||||
{
|
||||
vec3_t fv, rv, uv;
|
||||
|
||||
dl = CL_AllocDlight (i);
|
||||
VectorCopy (ent->origin, dl->origin);
|
||||
dl->origin[2] += 16;
|
||||
AngleVectors (ent->angles, fv, rv, uv);
|
||||
|
||||
VectorMA (dl->origin, 18, fv, dl->origin);
|
||||
dl->radius = 200 + (rand()&31);
|
||||
dl->minlight = 32;
|
||||
dl->die = cl.time + 0.1;
|
||||
|
||||
//johnfitz -- assume muzzle flash accompanied by muzzle flare, which looks bad when lerped
|
||||
if (r_lerpmodels.value != 2)
|
||||
{
|
||||
if (ent == &cl_entities[cl.viewentity])
|
||||
cl.viewent.lerpflags |= LERP_RESETANIM|LERP_RESETANIM2; //no lerping for two frames
|
||||
else
|
||||
ent->lerpflags |= LERP_RESETANIM|LERP_RESETANIM2; //no lerping for two frames
|
||||
}
|
||||
//johnfitz
|
||||
}
|
||||
if (ent->effects & EF_BRIGHTLIGHT)
|
||||
{
|
||||
dl = CL_AllocDlight (i);
|
||||
VectorCopy (ent->origin, dl->origin);
|
||||
dl->origin[2] += 16;
|
||||
dl->radius = 400 + (rand()&31);
|
||||
dl->die = cl.time + 0.001;
|
||||
}
|
||||
if (ent->effects & EF_DIMLIGHT)
|
||||
{
|
||||
dl = CL_AllocDlight (i);
|
||||
VectorCopy (ent->origin, dl->origin);
|
||||
dl->radius = 200 + (rand()&31);
|
||||
dl->die = cl.time + 0.001;
|
||||
}
|
||||
if (ent->effects & EF_QEX_QUADLIGHT)
|
||||
{
|
||||
dl = CL_AllocDlight (i);
|
||||
VectorCopy (ent->origin, dl->origin);
|
||||
dl->radius = 200 + (rand()&31);
|
||||
dl->die = cl.time + 0.001;
|
||||
dl->color[0] = 0.25f;
|
||||
dl->color[1] = 0.25f;
|
||||
dl->color[2] = 1.0f;
|
||||
}
|
||||
if (ent->effects & EF_QEX_PENTALIGHT)
|
||||
{
|
||||
dl = CL_AllocDlight (i);
|
||||
VectorCopy (ent->origin, dl->origin);
|
||||
dl->radius = 200 + (rand()&31);
|
||||
dl->die = cl.time + 0.001;
|
||||
dl->color[0] = 1.0f;
|
||||
dl->color[1] = 0.25f;
|
||||
dl->color[2] = 0.25f;
|
||||
}
|
||||
|
||||
if (ent->model->flags & EF_GIB)
|
||||
R_RocketTrail (oldorg, ent->origin, 2);
|
||||
else if (ent->model->flags & EF_ZOMGIB)
|
||||
R_RocketTrail (oldorg, ent->origin, 4);
|
||||
else if (ent->model->flags & EF_TRACER)
|
||||
R_RocketTrail (oldorg, ent->origin, 3);
|
||||
else if (ent->model->flags & EF_TRACER2)
|
||||
R_RocketTrail (oldorg, ent->origin, 5);
|
||||
else if (ent->model->flags & EF_ROCKET)
|
||||
{
|
||||
R_RocketTrail (oldorg, ent->origin, 0);
|
||||
dl = CL_AllocDlight (i);
|
||||
VectorCopy (ent->origin, dl->origin);
|
||||
dl->radius = 200;
|
||||
dl->die = cl.time + 0.01;
|
||||
}
|
||||
else if (ent->model->flags & EF_GRENADE)
|
||||
R_RocketTrail (oldorg, ent->origin, 1);
|
||||
else if (ent->model->flags & EF_TRACER3)
|
||||
R_RocketTrail (oldorg, ent->origin, 6);
|
||||
|
||||
ent->forcelink = false;
|
||||
|
||||
if (i == cl.viewentity && !chase_active.value)
|
||||
continue;
|
||||
|
||||
if (cl_numvisedicts < MAX_VISEDICTS)
|
||||
{
|
||||
cl_visedicts[cl_numvisedicts] = ent;
|
||||
cl_numvisedicts++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_ReadFromServer
|
||||
|
||||
Read all incoming data from the server
|
||||
===============
|
||||
*/
|
||||
int CL_ReadFromServer (void)
|
||||
{
|
||||
int ret;
|
||||
extern int num_temp_entities; //johnfitz
|
||||
int num_beams = 0; //johnfitz
|
||||
int num_dlights = 0; //johnfitz
|
||||
beam_t *b; //johnfitz
|
||||
dlight_t *l; //johnfitz
|
||||
int i; //johnfitz
|
||||
|
||||
|
||||
cl.oldtime = cl.time;
|
||||
cl.time += host_frametime;
|
||||
|
||||
do
|
||||
{
|
||||
ret = CL_GetMessage ();
|
||||
if (ret == -1)
|
||||
Host_Error ("CL_ReadFromServer: lost server connection");
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
cl.last_received_message = realtime;
|
||||
CL_ParseServerMessage ();
|
||||
} while (ret && cls.state == ca_connected);
|
||||
|
||||
if (cl_shownet.value)
|
||||
Con_Printf ("\n");
|
||||
|
||||
CL_RelinkEntities ();
|
||||
CL_UpdateTEnts ();
|
||||
|
||||
//johnfitz -- devstats
|
||||
|
||||
//visedicts
|
||||
if (cl_numvisedicts > 256 && dev_peakstats.visedicts <= 256)
|
||||
Con_DWarning ("%i visedicts exceeds standard limit of 256 (max = %d).\n", cl_numvisedicts, MAX_VISEDICTS);
|
||||
dev_stats.visedicts = cl_numvisedicts;
|
||||
dev_peakstats.visedicts = q_max(cl_numvisedicts, dev_peakstats.visedicts);
|
||||
|
||||
//temp entities
|
||||
if (num_temp_entities > 64 && dev_peakstats.tempents <= 64)
|
||||
Con_DWarning ("%i tempentities exceeds standard limit of 64 (max = %d).\n", num_temp_entities, MAX_TEMP_ENTITIES);
|
||||
dev_stats.tempents = num_temp_entities;
|
||||
dev_peakstats.tempents = q_max(num_temp_entities, dev_peakstats.tempents);
|
||||
|
||||
//beams
|
||||
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
|
||||
if (b->model && b->endtime >= cl.time)
|
||||
num_beams++;
|
||||
if (num_beams > 24 && dev_peakstats.beams <= 24)
|
||||
Con_DWarning ("%i beams exceeded standard limit of 24 (max = %d).\n", num_beams, MAX_BEAMS);
|
||||
dev_stats.beams = num_beams;
|
||||
dev_peakstats.beams = q_max(num_beams, dev_peakstats.beams);
|
||||
|
||||
//dlights
|
||||
for (i=0, l=cl_dlights ; i<MAX_DLIGHTS ; i++, l++)
|
||||
if (l->die >= cl.time && l->radius)
|
||||
num_dlights++;
|
||||
if (num_dlights > 32 && dev_peakstats.dlights <= 32)
|
||||
Con_DWarning ("%i dlights exceeded standard limit of 32 (max = %d).\n", num_dlights, MAX_DLIGHTS);
|
||||
dev_stats.dlights = num_dlights;
|
||||
dev_peakstats.dlights = q_max(num_dlights, dev_peakstats.dlights);
|
||||
|
||||
//johnfitz
|
||||
|
||||
//
|
||||
// bring the links up to date
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_SendCmd
|
||||
=================
|
||||
*/
|
||||
void CL_SendCmd (void)
|
||||
{
|
||||
usercmd_t cmd;
|
||||
|
||||
if (cls.state != ca_connected)
|
||||
return;
|
||||
|
||||
if (cls.signon == SIGNONS)
|
||||
{
|
||||
// get basic movement from keyboard
|
||||
CL_BaseMove (&cmd);
|
||||
|
||||
// allow mice or other external controllers to add to the move
|
||||
IN_Move (&cmd);
|
||||
|
||||
// send the unreliable message
|
||||
CL_SendMove (&cmd);
|
||||
}
|
||||
|
||||
if (cls.demoplayback)
|
||||
{
|
||||
SZ_Clear (&cls.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// send the reliable message
|
||||
if (!cls.message.cursize)
|
||||
return; // no message at all
|
||||
|
||||
if (!NET_CanSendMessage (cls.netcon))
|
||||
{
|
||||
Con_DPrintf ("CL_SendCmd: can't send\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (NET_SendMessage (cls.netcon, &cls.message) == -1)
|
||||
Host_Error ("CL_SendCmd: lost server connection");
|
||||
|
||||
SZ_Clear (&cls.message);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_Tracepos_f -- johnfitz
|
||||
|
||||
display impact point of trace along VPN
|
||||
=============
|
||||
*/
|
||||
void CL_Tracepos_f (void)
|
||||
{
|
||||
vec3_t v, w;
|
||||
|
||||
if (cls.state != ca_connected)
|
||||
return;
|
||||
|
||||
VectorMA(r_refdef.vieworg, 8192.0, vpn, v);
|
||||
TraceLine(r_refdef.vieworg, v, w);
|
||||
|
||||
if (VectorLength(w) == 0)
|
||||
Con_Printf ("Tracepos: trace didn't hit anything\n");
|
||||
else
|
||||
Con_Printf ("Tracepos: (%i %i %i)\n", (int)w[0], (int)w[1], (int)w[2]);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_Viewpos_f -- johnfitz
|
||||
|
||||
display client's position and angles
|
||||
=============
|
||||
*/
|
||||
void CL_Viewpos_f (void)
|
||||
{
|
||||
if (cls.state != ca_connected)
|
||||
return;
|
||||
#if 0
|
||||
//camera position
|
||||
Con_Printf ("Viewpos: (%i %i %i) %i %i %i\n",
|
||||
(int)r_refdef.vieworg[0],
|
||||
(int)r_refdef.vieworg[1],
|
||||
(int)r_refdef.vieworg[2],
|
||||
(int)r_refdef.viewangles[PITCH],
|
||||
(int)r_refdef.viewangles[YAW],
|
||||
(int)r_refdef.viewangles[ROLL]);
|
||||
#else
|
||||
//player position
|
||||
Con_Printf ("Viewpos: (%i %i %i) %i %i %i\n",
|
||||
(int)cl_entities[cl.viewentity].origin[0],
|
||||
(int)cl_entities[cl.viewentity].origin[1],
|
||||
(int)cl_entities[cl.viewentity].origin[2],
|
||||
(int)cl.viewangles[PITCH],
|
||||
(int)cl.viewangles[YAW],
|
||||
(int)cl.viewangles[ROLL]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_Init
|
||||
=================
|
||||
*/
|
||||
void CL_Init (void)
|
||||
{
|
||||
SZ_Alloc (&cls.message, 1024);
|
||||
|
||||
CL_InitInput ();
|
||||
CL_InitTEnts ();
|
||||
|
||||
Cvar_RegisterVariable (&cl_name);
|
||||
Cvar_RegisterVariable (&cl_color);
|
||||
Cvar_RegisterVariable (&cl_upspeed);
|
||||
Cvar_RegisterVariable (&cl_forwardspeed);
|
||||
Cvar_RegisterVariable (&cl_backspeed);
|
||||
Cvar_RegisterVariable (&cl_sidespeed);
|
||||
Cvar_RegisterVariable (&cl_movespeedkey);
|
||||
Cvar_RegisterVariable (&cl_yawspeed);
|
||||
Cvar_RegisterVariable (&cl_pitchspeed);
|
||||
Cvar_RegisterVariable (&cl_anglespeedkey);
|
||||
Cvar_RegisterVariable (&cl_shownet);
|
||||
Cvar_RegisterVariable (&cl_nolerp);
|
||||
Cvar_RegisterVariable (&lookspring);
|
||||
Cvar_RegisterVariable (&lookstrafe);
|
||||
Cvar_RegisterVariable (&sensitivity);
|
||||
|
||||
Cvar_RegisterVariable (&cl_alwaysrun);
|
||||
|
||||
Cvar_RegisterVariable (&m_pitch);
|
||||
Cvar_RegisterVariable (&m_yaw);
|
||||
Cvar_RegisterVariable (&m_forward);
|
||||
Cvar_RegisterVariable (&m_side);
|
||||
|
||||
Cvar_RegisterVariable (&cfg_unbindall);
|
||||
|
||||
Cvar_RegisterVariable (&cl_maxpitch); //johnfitz -- variable pitch clamping
|
||||
Cvar_RegisterVariable (&cl_minpitch); //johnfitz -- variable pitch clamping
|
||||
|
||||
Cvar_RegisterVariable (&cl_startdemos);
|
||||
|
||||
Cmd_AddCommand ("entities", CL_PrintEntities_f);
|
||||
Cmd_AddCommand ("disconnect", CL_Disconnect_f);
|
||||
Cmd_AddCommand ("record", CL_Record_f);
|
||||
Cmd_AddCommand ("stop", CL_Stop_f);
|
||||
Cmd_AddCommand ("playdemo", CL_PlayDemo_f);
|
||||
Cmd_AddCommand ("timedemo", CL_TimeDemo_f);
|
||||
|
||||
Cmd_AddCommand ("tracepos", CL_Tracepos_f); //johnfitz
|
||||
Cmd_AddCommand ("viewpos", CL_Viewpos_f); //johnfitz
|
||||
}
|
||||
|
||||
+1260
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// cl_tent.c -- client side temporary entities
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
int num_temp_entities;
|
||||
entity_t cl_temp_entities[MAX_TEMP_ENTITIES];
|
||||
beam_t cl_beams[MAX_BEAMS];
|
||||
|
||||
sfx_t *cl_sfx_wizhit;
|
||||
sfx_t *cl_sfx_knighthit;
|
||||
sfx_t *cl_sfx_tink1;
|
||||
sfx_t *cl_sfx_ric1;
|
||||
sfx_t *cl_sfx_ric2;
|
||||
sfx_t *cl_sfx_ric3;
|
||||
sfx_t *cl_sfx_r_exp3;
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_ParseTEnt
|
||||
=================
|
||||
*/
|
||||
void CL_InitTEnts (void)
|
||||
{
|
||||
cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
|
||||
cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
|
||||
cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
|
||||
cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
|
||||
cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
|
||||
cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
|
||||
cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_ParseBeam
|
||||
=================
|
||||
*/
|
||||
void CL_ParseBeam (qmodel_t *m)
|
||||
{
|
||||
int ent;
|
||||
vec3_t start, end;
|
||||
beam_t *b;
|
||||
int i;
|
||||
|
||||
ent = MSG_ReadShort ();
|
||||
|
||||
start[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
start[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
start[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
|
||||
end[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
end[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
end[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
|
||||
// override any beam with the same entity
|
||||
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
|
||||
if (b->entity == ent)
|
||||
{
|
||||
b->entity = ent;
|
||||
b->model = m;
|
||||
b->endtime = cl.time + 0.2;
|
||||
VectorCopy (start, b->start);
|
||||
VectorCopy (end, b->end);
|
||||
return;
|
||||
}
|
||||
|
||||
// find a free beam
|
||||
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
|
||||
{
|
||||
if (!b->model || b->endtime < cl.time)
|
||||
{
|
||||
b->entity = ent;
|
||||
b->model = m;
|
||||
b->endtime = cl.time + 0.2;
|
||||
VectorCopy (start, b->start);
|
||||
VectorCopy (end, b->end);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//johnfitz -- less spammy overflow message
|
||||
if (!dev_overflows.beams || dev_overflows.beams + CONSOLE_RESPAM_TIME < realtime )
|
||||
{
|
||||
Con_Printf ("Beam list overflow!\n");
|
||||
dev_overflows.beams = realtime;
|
||||
}
|
||||
//johnfitz
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_ParseTEnt
|
||||
=================
|
||||
*/
|
||||
void CL_ParseTEnt (void)
|
||||
{
|
||||
int type;
|
||||
vec3_t pos;
|
||||
dlight_t *dl;
|
||||
int rnd;
|
||||
int colorStart, colorLength;
|
||||
|
||||
type = MSG_ReadByte ();
|
||||
switch (type)
|
||||
{
|
||||
case TE_WIZSPIKE: // spike hitting wall
|
||||
pos[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
R_RunParticleEffect (pos, vec3_origin, 20, 30);
|
||||
S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
|
||||
break;
|
||||
|
||||
case TE_KNIGHTSPIKE: // spike hitting wall
|
||||
pos[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
R_RunParticleEffect (pos, vec3_origin, 226, 20);
|
||||
S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
|
||||
break;
|
||||
|
||||
case TE_SPIKE: // spike hitting wall
|
||||
pos[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
R_RunParticleEffect (pos, vec3_origin, 0, 10);
|
||||
if ( rand() % 5 )
|
||||
S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
|
||||
else
|
||||
{
|
||||
rnd = rand() & 3;
|
||||
if (rnd == 1)
|
||||
S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
|
||||
else if (rnd == 2)
|
||||
S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
|
||||
else
|
||||
S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
|
||||
}
|
||||
break;
|
||||
case TE_SUPERSPIKE: // super spike hitting wall
|
||||
pos[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
R_RunParticleEffect (pos, vec3_origin, 0, 20);
|
||||
|
||||
if ( rand() % 5 )
|
||||
S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
|
||||
else
|
||||
{
|
||||
rnd = rand() & 3;
|
||||
if (rnd == 1)
|
||||
S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
|
||||
else if (rnd == 2)
|
||||
S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
|
||||
else
|
||||
S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case TE_GUNSHOT: // bullet hitting wall
|
||||
pos[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
R_RunParticleEffect (pos, vec3_origin, 0, 20);
|
||||
break;
|
||||
|
||||
case TE_EXPLOSION: // rocket explosion
|
||||
pos[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
R_ParticleExplosion (pos);
|
||||
dl = CL_AllocDlight (0);
|
||||
VectorCopy (pos, dl->origin);
|
||||
dl->radius = 350;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->decay = 300;
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
|
||||
break;
|
||||
|
||||
case TE_TAREXPLOSION: // tarbaby explosion
|
||||
pos[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
R_BlobExplosion (pos);
|
||||
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
|
||||
break;
|
||||
|
||||
case TE_LIGHTNING1: // lightning bolts
|
||||
CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
|
||||
break;
|
||||
|
||||
case TE_LIGHTNING2: // lightning bolts
|
||||
CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
|
||||
break;
|
||||
|
||||
case TE_LIGHTNING3: // lightning bolts
|
||||
CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
|
||||
break;
|
||||
|
||||
// PGM 01/21/97
|
||||
case TE_BEAM: // grappling hook beam
|
||||
CL_ParseBeam (Mod_ForName("progs/beam.mdl", true));
|
||||
break;
|
||||
// PGM 01/21/97
|
||||
|
||||
case TE_LAVASPLASH:
|
||||
pos[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
R_LavaSplash (pos);
|
||||
break;
|
||||
|
||||
case TE_TELEPORT:
|
||||
pos[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
R_TeleportSplash (pos);
|
||||
break;
|
||||
|
||||
case TE_EXPLOSION2: // color mapped explosion
|
||||
pos[0] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[1] = MSG_ReadCoord (cl.protocolflags);
|
||||
pos[2] = MSG_ReadCoord (cl.protocolflags);
|
||||
colorStart = MSG_ReadByte ();
|
||||
colorLength = MSG_ReadByte ();
|
||||
R_ParticleExplosion2 (pos, colorStart, colorLength);
|
||||
dl = CL_AllocDlight (0);
|
||||
VectorCopy (pos, dl->origin);
|
||||
dl->radius = 350;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->decay = 300;
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
Sys_Error ("CL_ParseTEnt: bad type");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_NewTempEntity
|
||||
=================
|
||||
*/
|
||||
entity_t *CL_NewTempEntity (void)
|
||||
{
|
||||
entity_t *ent;
|
||||
|
||||
if (cl_numvisedicts == MAX_VISEDICTS)
|
||||
return NULL;
|
||||
if (num_temp_entities == MAX_TEMP_ENTITIES)
|
||||
return NULL;
|
||||
ent = &cl_temp_entities[num_temp_entities];
|
||||
memset (ent, 0, sizeof(*ent));
|
||||
num_temp_entities++;
|
||||
cl_visedicts[cl_numvisedicts] = ent;
|
||||
cl_numvisedicts++;
|
||||
ent->scale = ENTSCALE_DEFAULT;
|
||||
ent->colormap = vid.colormap;
|
||||
return ent;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_UpdateTEnts
|
||||
=================
|
||||
*/
|
||||
void CL_UpdateTEnts (void)
|
||||
{
|
||||
int i, j; //johnfitz -- use j instead of using i twice, so we don't corrupt memory
|
||||
beam_t *b;
|
||||
vec3_t dist, org;
|
||||
float d;
|
||||
entity_t *ent;
|
||||
float yaw, pitch;
|
||||
float forward;
|
||||
|
||||
num_temp_entities = 0;
|
||||
|
||||
srand ((int) (cl.time * 1000)); //johnfitz -- freeze beams when paused
|
||||
|
||||
// update lightning
|
||||
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
|
||||
{
|
||||
if (!b->model || b->endtime < cl.time)
|
||||
continue;
|
||||
|
||||
// if coming from the player, update the start position
|
||||
if (b->entity == cl.viewentity)
|
||||
{
|
||||
VectorCopy (cl_entities[cl.viewentity].origin, b->start);
|
||||
}
|
||||
|
||||
// calculate pitch and yaw
|
||||
VectorSubtract (b->end, b->start, dist);
|
||||
|
||||
if (dist[1] == 0 && dist[0] == 0)
|
||||
{
|
||||
yaw = 0;
|
||||
if (dist[2] > 0)
|
||||
pitch = 90;
|
||||
else
|
||||
pitch = 270;
|
||||
}
|
||||
else
|
||||
{
|
||||
yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
|
||||
if (yaw < 0)
|
||||
yaw += 360;
|
||||
|
||||
forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
|
||||
pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
|
||||
if (pitch < 0)
|
||||
pitch += 360;
|
||||
}
|
||||
|
||||
// add new entities for the lightning
|
||||
VectorCopy (b->start, org);
|
||||
d = VectorNormalize(dist);
|
||||
while (d > 0)
|
||||
{
|
||||
ent = CL_NewTempEntity ();
|
||||
if (!ent)
|
||||
return;
|
||||
VectorCopy (org, ent->origin);
|
||||
ent->model = b->model;
|
||||
ent->angles[0] = pitch;
|
||||
ent->angles[1] = yaw;
|
||||
ent->angles[2] = rand()%360;
|
||||
|
||||
//johnfitz -- use j instead of using i twice, so we don't corrupt memory
|
||||
for (j=0 ; j<3 ; j++)
|
||||
org[j] += dist[j]*30;
|
||||
d -= 30;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 _CLIENT_H_
|
||||
#define _CLIENT_H_
|
||||
|
||||
// client.h
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int length;
|
||||
char map[MAX_STYLESTRING];
|
||||
char average; //johnfitz
|
||||
char peak; //johnfitz
|
||||
} lightstyle_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[MAX_SCOREBOARDNAME];
|
||||
float entertime;
|
||||
int frags;
|
||||
int colors; // two 4 bit fields
|
||||
byte translations[VID_GRADES*256];
|
||||
} scoreboard_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int destcolor[3];
|
||||
int percent; // 0-256
|
||||
} cshift_t;
|
||||
|
||||
#define CSHIFT_CONTENTS 0
|
||||
#define CSHIFT_DAMAGE 1
|
||||
#define CSHIFT_BONUS 2
|
||||
#define CSHIFT_POWERUP 3
|
||||
#define NUM_CSHIFTS 4
|
||||
|
||||
#define NAME_LENGTH 64
|
||||
|
||||
|
||||
//
|
||||
// client_state_t should hold all pieces of the client state
|
||||
//
|
||||
|
||||
#define SIGNONS 4 // signon messages to receive before connected
|
||||
|
||||
#define MAX_DLIGHTS 64 //johnfitz -- was 32
|
||||
typedef struct
|
||||
{
|
||||
vec3_t origin;
|
||||
float radius;
|
||||
float die; // stop lighting after this time
|
||||
float decay; // drop this each second
|
||||
float minlight; // don't add when contributing less
|
||||
int key;
|
||||
vec3_t color; //johnfitz -- lit support via lordhavoc
|
||||
} dlight_t;
|
||||
|
||||
|
||||
#define MAX_BEAMS 32 //johnfitz -- was 24
|
||||
typedef struct
|
||||
{
|
||||
int entity;
|
||||
struct qmodel_s *model;
|
||||
float endtime;
|
||||
vec3_t start, end;
|
||||
} beam_t;
|
||||
|
||||
#define MAX_MAPSTRING 2048
|
||||
#define MAX_DEMOS 8
|
||||
#define MAX_DEMONAME 16
|
||||
|
||||
typedef enum {
|
||||
ca_dedicated, // a dedicated server with no ability to start a client
|
||||
ca_disconnected, // full screen console with no connection
|
||||
ca_connected // valid netcon, talking to a server
|
||||
} cactive_t;
|
||||
|
||||
//
|
||||
// the client_static_t structure is persistant through an arbitrary number
|
||||
// of server connections
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
cactive_t state;
|
||||
|
||||
// personalization data sent to server
|
||||
char spawnparms[MAX_MAPSTRING]; // to restart a level
|
||||
|
||||
// demo loop control
|
||||
int demonum; // -1 = don't play demos
|
||||
char demos[MAX_DEMOS][MAX_DEMONAME]; // when not playing
|
||||
|
||||
// demo recording info must be here, because record is started before
|
||||
// entering a map (and clearing client_state_t)
|
||||
qboolean demorecording;
|
||||
qboolean demoplayback;
|
||||
|
||||
// did the user pause demo playback? (separate from cl.paused because we don't
|
||||
// want a svc_setpause inside the demo to actually pause demo playback).
|
||||
qboolean demopaused;
|
||||
|
||||
qboolean timedemo;
|
||||
int forcetrack; // -1 = use normal cd track
|
||||
FILE *demofile;
|
||||
int td_lastframe; // to meter out one message a frame
|
||||
int td_startframe; // host_framecount at start
|
||||
float td_starttime; // realtime at second frame of timedemo
|
||||
|
||||
// connection information
|
||||
int signon; // 0 to SIGNONS
|
||||
struct qsocket_s *netcon;
|
||||
sizebuf_t message; // writing buffer to send to server
|
||||
|
||||
} client_static_t;
|
||||
|
||||
extern client_static_t cls;
|
||||
|
||||
//
|
||||
// the client_state_t structure is wiped completely at every
|
||||
// server signon
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
int movemessages; // since connecting to this server
|
||||
// throw out the first couple, so the player
|
||||
// doesn't accidentally do something the
|
||||
// first frame
|
||||
usercmd_t cmd; // last command sent to the server
|
||||
|
||||
// information for local display
|
||||
int stats[MAX_CL_STATS]; // health, etc
|
||||
int items; // inventory bit flags
|
||||
float item_gettime[32]; // cl.time of aquiring item, for blinking
|
||||
float faceanimtime; // use anim frame if cl.time < this
|
||||
|
||||
cshift_t cshifts[NUM_CSHIFTS]; // color shifts for damage, powerups
|
||||
cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types
|
||||
|
||||
// the client maintains its own idea of view angles, which are
|
||||
// sent to the server each frame. The server sets punchangle when
|
||||
// the view is temporarliy offset, and an angle reset commands at the start
|
||||
// of each level and after teleporting.
|
||||
vec3_t mviewangles[2]; // during demo playback viewangles is lerped
|
||||
// between these
|
||||
vec3_t viewangles;
|
||||
|
||||
vec3_t mvelocity[2]; // update by server, used for lean+bob
|
||||
// (0 is newest)
|
||||
vec3_t velocity; // lerped between mvelocity[0] and [1]
|
||||
|
||||
vec3_t punchangle; // temporary offset
|
||||
|
||||
// pitch drifting vars
|
||||
float idealpitch;
|
||||
float pitchvel;
|
||||
qboolean nodrift;
|
||||
float driftmove;
|
||||
double laststop;
|
||||
|
||||
float viewheight;
|
||||
float crouch; // local amount for smoothing stepups
|
||||
|
||||
qboolean paused; // send over by server
|
||||
qboolean onground;
|
||||
qboolean inwater;
|
||||
|
||||
int intermission; // don't change view angle, full screen, etc
|
||||
int completed_time; // latched at intermission start
|
||||
|
||||
double mtime[2]; // the timestamp of last two messages
|
||||
double time; // clients view of time, should be between
|
||||
// servertime and oldservertime to generate
|
||||
// a lerp point for other data
|
||||
double oldtime; // previous cl.time, time-oldtime is used
|
||||
// to decay light values and smooth step ups
|
||||
|
||||
|
||||
float last_received_message; // (realtime) for net trouble icon
|
||||
|
||||
//
|
||||
// information that is static for the entire time connected to a server
|
||||
//
|
||||
struct qmodel_s *model_precache[MAX_MODELS];
|
||||
struct sfx_s *sound_precache[MAX_SOUNDS];
|
||||
|
||||
char mapname[128];
|
||||
char levelname[128]; // for display on solo scoreboard //johnfitz -- was 40.
|
||||
int viewentity; // cl_entitites[cl.viewentity] = player
|
||||
int maxclients;
|
||||
int gametype;
|
||||
|
||||
// refresh related state
|
||||
struct qmodel_s *worldmodel; // cl_entitites[0].model
|
||||
struct efrag_s *free_efrags;
|
||||
int num_efrags;
|
||||
int num_entities; // held in cl_entities array
|
||||
int num_statics; // held in cl_staticentities array
|
||||
entity_t viewent; // the gun model
|
||||
|
||||
int cdtrack, looptrack; // cd audio
|
||||
|
||||
// frag scoreboard
|
||||
scoreboard_t *scores; // [cl.maxclients]
|
||||
|
||||
unsigned protocol; //johnfitz
|
||||
unsigned protocolflags;
|
||||
} client_state_t;
|
||||
|
||||
|
||||
//
|
||||
// cvars
|
||||
//
|
||||
extern cvar_t cl_name;
|
||||
extern cvar_t cl_color;
|
||||
|
||||
extern cvar_t cl_upspeed;
|
||||
extern cvar_t cl_forwardspeed;
|
||||
extern cvar_t cl_backspeed;
|
||||
extern cvar_t cl_sidespeed;
|
||||
|
||||
extern cvar_t cl_movespeedkey;
|
||||
|
||||
extern cvar_t cl_yawspeed;
|
||||
extern cvar_t cl_pitchspeed;
|
||||
|
||||
extern cvar_t cl_anglespeedkey;
|
||||
|
||||
extern cvar_t cl_alwaysrun; // QuakeSpasm
|
||||
|
||||
extern cvar_t cl_autofire;
|
||||
|
||||
extern cvar_t cl_shownet;
|
||||
extern cvar_t cl_nolerp;
|
||||
|
||||
extern cvar_t cfg_unbindall;
|
||||
|
||||
extern cvar_t cl_pitchdriftspeed;
|
||||
extern cvar_t lookspring;
|
||||
extern cvar_t lookstrafe;
|
||||
extern cvar_t sensitivity;
|
||||
|
||||
extern cvar_t m_pitch;
|
||||
extern cvar_t m_yaw;
|
||||
extern cvar_t m_forward;
|
||||
extern cvar_t m_side;
|
||||
|
||||
extern cvar_t cl_startdemos;
|
||||
|
||||
|
||||
#define MAX_TEMP_ENTITIES 256 //johnfitz -- was 64
|
||||
#define MAX_STATIC_ENTITIES 4096 //ericw -- was 512 //johnfitz -- was 128
|
||||
#define MAX_VISEDICTS 4096 // larger, now we support BSP2
|
||||
|
||||
extern client_state_t cl;
|
||||
|
||||
// FIXME, allocate dynamically
|
||||
extern entity_t cl_static_entities[MAX_STATIC_ENTITIES];
|
||||
extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
|
||||
extern dlight_t cl_dlights[MAX_DLIGHTS];
|
||||
extern entity_t cl_temp_entities[MAX_TEMP_ENTITIES];
|
||||
extern beam_t cl_beams[MAX_BEAMS];
|
||||
extern entity_t *cl_visedicts[MAX_VISEDICTS];
|
||||
extern int cl_numvisedicts;
|
||||
|
||||
extern entity_t *cl_entities; //johnfitz -- was a static array, now on hunk
|
||||
extern int cl_max_edicts; //johnfitz -- only changes when new map loads
|
||||
|
||||
//=============================================================================
|
||||
|
||||
//
|
||||
// cl_main
|
||||
//
|
||||
dlight_t *CL_AllocDlight (int key);
|
||||
void CL_DecayLights (void);
|
||||
|
||||
void CL_Init (void);
|
||||
|
||||
void CL_EstablishConnection (const char *host);
|
||||
void CL_Signon1 (void);
|
||||
void CL_Signon2 (void);
|
||||
void CL_Signon3 (void);
|
||||
void CL_Signon4 (void);
|
||||
|
||||
void CL_Disconnect (void);
|
||||
void CL_Disconnect_f (void);
|
||||
void CL_NextDemo (void);
|
||||
|
||||
//
|
||||
// cl_input
|
||||
//
|
||||
typedef struct
|
||||
{
|
||||
int down[2]; // key nums holding it down
|
||||
int state; // low bit is down state
|
||||
} kbutton_t;
|
||||
|
||||
extern kbutton_t in_mlook, in_klook;
|
||||
extern kbutton_t in_strafe;
|
||||
extern kbutton_t in_speed;
|
||||
|
||||
void CL_InitInput (void);
|
||||
void CL_SendCmd (void);
|
||||
void CL_SendMove (const usercmd_t *cmd);
|
||||
int CL_ReadFromServer (void);
|
||||
void CL_BaseMove (usercmd_t *cmd);
|
||||
|
||||
void CL_ParseTEnt (void);
|
||||
void CL_UpdateTEnts (void);
|
||||
|
||||
void CL_ClearState (void);
|
||||
|
||||
//
|
||||
// cl_demo.c
|
||||
//
|
||||
void CL_StopPlayback (void);
|
||||
int CL_GetMessage (void);
|
||||
void CL_ClearSignons (void);
|
||||
|
||||
void CL_Stop_f (void);
|
||||
void CL_Record_f (void);
|
||||
void CL_PlayDemo_f (void);
|
||||
void CL_TimeDemo_f (void);
|
||||
|
||||
//
|
||||
// cl_parse.c
|
||||
//
|
||||
void CL_ParseServerMessage (void);
|
||||
void CL_NewTranslation (int slot);
|
||||
|
||||
//
|
||||
// view
|
||||
//
|
||||
void V_StartPitchDrift (void);
|
||||
void V_StopPitchDrift (void);
|
||||
|
||||
void V_RenderView (void);
|
||||
//void V_UpdatePalette (void); //johnfitz
|
||||
void V_Register (void);
|
||||
void V_ParseDamage (void);
|
||||
void V_SetContentsColor (int contents);
|
||||
|
||||
//
|
||||
// cl_tent
|
||||
//
|
||||
void CL_InitTEnts (void);
|
||||
void CL_SignonReply (void);
|
||||
|
||||
//
|
||||
// chase
|
||||
//
|
||||
extern cvar_t chase_active;
|
||||
|
||||
void Chase_Init (void);
|
||||
void TraceLine (vec3_t start, vec3_t end, vec3_t impact);
|
||||
void Chase_UpdateForClient (void); //johnfitz
|
||||
void Chase_UpdateForDrawing (void); //johnfitz
|
||||
|
||||
#endif /* _CLIENT_H_ */
|
||||
|
||||
+869
@@ -0,0 +1,869 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2007-2008 Kristian Duske
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// cmd.c -- Quake script command processing module
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
void Cmd_ForwardToServer (void);
|
||||
|
||||
#define MAX_ALIAS_NAME 32
|
||||
|
||||
#define CMDLINE_LENGTH 256 //johnfitz -- mirrored in common.c
|
||||
|
||||
typedef struct cmdalias_s
|
||||
{
|
||||
struct cmdalias_s *next;
|
||||
char name[MAX_ALIAS_NAME];
|
||||
char *value;
|
||||
} cmdalias_t;
|
||||
|
||||
cmdalias_t *cmd_alias;
|
||||
|
||||
qboolean cmd_wait;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_Wait_f
|
||||
|
||||
Causes execution of the remainder of the command buffer to be delayed until
|
||||
next frame. This allows commands like:
|
||||
bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2"
|
||||
============
|
||||
*/
|
||||
void Cmd_Wait_f (void)
|
||||
{
|
||||
cmd_wait = true;
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
COMMAND BUFFER
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
sizebuf_t cmd_text;
|
||||
|
||||
/*
|
||||
============
|
||||
Cbuf_Init
|
||||
============
|
||||
*/
|
||||
void Cbuf_Init (void)
|
||||
{
|
||||
SZ_Alloc (&cmd_text, 1<<18); // space for commands and script files. spike -- was 8192, but modern configs can be _HUGE_, at least if they contain lots of comments/docs for things.
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Cbuf_AddText
|
||||
|
||||
Adds command text at the end of the buffer
|
||||
============
|
||||
*/
|
||||
void Cbuf_AddText (const char *text)
|
||||
{
|
||||
int l;
|
||||
|
||||
l = Q_strlen (text);
|
||||
|
||||
if (cmd_text.cursize + l >= cmd_text.maxsize)
|
||||
{
|
||||
Con_Printf ("Cbuf_AddText: overflow\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SZ_Write (&cmd_text, text, Q_strlen (text));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Cbuf_InsertText
|
||||
|
||||
Adds command text immediately after the current command
|
||||
Adds a \n to the text
|
||||
FIXME: actually change the command buffer to do less copying
|
||||
============
|
||||
*/
|
||||
void Cbuf_InsertText (const char *text)
|
||||
{
|
||||
char *temp;
|
||||
int templen;
|
||||
|
||||
// copy off any commands still remaining in the exec buffer
|
||||
templen = cmd_text.cursize;
|
||||
if (templen)
|
||||
{
|
||||
temp = (char *) Z_Malloc (templen);
|
||||
Q_memcpy (temp, cmd_text.data, templen);
|
||||
SZ_Clear (&cmd_text);
|
||||
}
|
||||
else
|
||||
temp = NULL; // shut up compiler
|
||||
|
||||
// add the entire text of the file
|
||||
Cbuf_AddText (text);
|
||||
SZ_Write (&cmd_text, "\n", 1);
|
||||
// add the copied off data
|
||||
if (templen)
|
||||
{
|
||||
SZ_Write (&cmd_text, temp, templen);
|
||||
Z_Free (temp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cbuf_Execute
|
||||
============
|
||||
*/
|
||||
void Cbuf_Execute (void)
|
||||
{
|
||||
int i;
|
||||
char *text;
|
||||
char line[1024];
|
||||
int quotes;
|
||||
|
||||
while (cmd_text.cursize)
|
||||
{
|
||||
// find a \n or ; line break
|
||||
text = (char *)cmd_text.data;
|
||||
|
||||
quotes = 0;
|
||||
for (i=0 ; i< cmd_text.cursize ; i++)
|
||||
{
|
||||
if (text[i] == '"')
|
||||
quotes++;
|
||||
if ( !(quotes&1) && text[i] == ';')
|
||||
break; // don't break if inside a quoted string
|
||||
if (text[i] == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
if (i > (int)sizeof(line) - 1)
|
||||
{
|
||||
memcpy (line, text, sizeof(line) - 1);
|
||||
line[sizeof(line) - 1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (line, text, i);
|
||||
line[i] = 0;
|
||||
}
|
||||
|
||||
// delete the text from the command buffer and move remaining commands down
|
||||
// this is necessary because commands (exec, alias) can insert data at the
|
||||
// beginning of the text buffer
|
||||
|
||||
if (i == cmd_text.cursize)
|
||||
cmd_text.cursize = 0;
|
||||
else
|
||||
{
|
||||
i++;
|
||||
cmd_text.cursize -= i;
|
||||
memmove (text, text + i, cmd_text.cursize);
|
||||
}
|
||||
|
||||
// execute the command line
|
||||
Cmd_ExecuteString (line, src_command);
|
||||
|
||||
if (cmd_wait)
|
||||
{ // skip out while text still remains in buffer, leaving it
|
||||
// for next frame
|
||||
cmd_wait = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
SCRIPT COMMANDS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
===============
|
||||
Cmd_StuffCmds_f -- johnfitz -- rewritten to read the "cmdline" cvar, for use with dynamic mod loading
|
||||
|
||||
Adds command line parameters as script statements
|
||||
Commands lead with a +, and continue until a - or another +
|
||||
quake +prog jctest.qp +cmd amlev1
|
||||
quake -nosound +cmd amlev1
|
||||
===============
|
||||
*/
|
||||
void Cmd_StuffCmds_f (void)
|
||||
{
|
||||
extern cvar_t cmdline;
|
||||
char cmds[CMDLINE_LENGTH];
|
||||
int i, j, plus;
|
||||
|
||||
plus = false; // On Unix, argv[0] is command name
|
||||
|
||||
for (i = 0, j = 0; cmdline.string[i]; i++)
|
||||
{
|
||||
if (cmdline.string[i] == '+')
|
||||
{
|
||||
plus = true;
|
||||
if (j > 0)
|
||||
{
|
||||
cmds[j-1] = ';';
|
||||
cmds[j++] = ' ';
|
||||
}
|
||||
}
|
||||
else if (cmdline.string[i] == '-' &&
|
||||
(i==0 || cmdline.string[i-1] == ' ')) //johnfitz -- allow hypenated map names with +map
|
||||
plus = false;
|
||||
else if (plus)
|
||||
cmds[j++] = cmdline.string[i];
|
||||
}
|
||||
cmds[j] = 0;
|
||||
|
||||
Cbuf_InsertText (cmds);
|
||||
}
|
||||
|
||||
/* id1/pak0.pak from 2021 re-release doesn't have a default.cfg
|
||||
* embedding Quakespasm's customized default.cfg for that... */
|
||||
#include "default_cfg.hpp"
|
||||
|
||||
/*
|
||||
===============
|
||||
Cmd_Exec_f
|
||||
===============
|
||||
*/
|
||||
void Cmd_Exec_f (void)
|
||||
{
|
||||
const char *f;
|
||||
int mark;
|
||||
|
||||
if (Cmd_Argc () != 2)
|
||||
{
|
||||
Con_Printf ("exec <filename> : execute a script file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mark = Hunk_LowMark ();
|
||||
f = (const char *)COM_LoadHunkFile (Cmd_Argv(1), NULL);
|
||||
if (!f && !strcmp(Cmd_Argv(1), "default.cfg")) {
|
||||
f = default_cfg; /* see above.. */
|
||||
}
|
||||
if (!f)
|
||||
{
|
||||
Con_Printf ("couldn't exec %s\n",Cmd_Argv(1));
|
||||
return;
|
||||
}
|
||||
Con_Printf ("execing %s\n",Cmd_Argv(1));
|
||||
|
||||
Cbuf_InsertText (f);
|
||||
if (f != default_cfg) {
|
||||
Hunk_FreeToLowMark (mark);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Cmd_Echo_f
|
||||
|
||||
Just prints the rest of the line to the console
|
||||
===============
|
||||
*/
|
||||
void Cmd_Echo_f (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=1 ; i<Cmd_Argc() ; i++)
|
||||
Con_Printf ("%s ",Cmd_Argv(i));
|
||||
Con_Printf ("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Cmd_Alias_f -- johnfitz -- rewritten
|
||||
|
||||
Creates a new command that executes a command string (possibly ; seperated)
|
||||
===============
|
||||
*/
|
||||
void Cmd_Alias_f (void)
|
||||
{
|
||||
cmdalias_t *a;
|
||||
char cmd[1024];
|
||||
int i, c;
|
||||
const char *s;
|
||||
|
||||
|
||||
switch (Cmd_Argc())
|
||||
{
|
||||
case 1: //list all aliases
|
||||
for (a = cmd_alias, i = 0; a; a=a->next, i++)
|
||||
Con_SafePrintf (" %s: %s", a->name, a->value);
|
||||
if (i)
|
||||
Con_SafePrintf ("%i alias command(s)\n", i);
|
||||
else
|
||||
Con_SafePrintf ("no alias commands found\n");
|
||||
break;
|
||||
case 2: //output current alias string
|
||||
for (a = cmd_alias ; a ; a=a->next)
|
||||
if (!strcmp(Cmd_Argv(1), a->name))
|
||||
Con_Printf (" %s: %s", a->name, a->value);
|
||||
break;
|
||||
default: //set alias string
|
||||
s = Cmd_Argv(1);
|
||||
if (strlen(s) >= MAX_ALIAS_NAME)
|
||||
{
|
||||
Con_Printf ("Alias name is too long\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// if the alias already exists, reuse it
|
||||
for (a = cmd_alias ; a ; a=a->next)
|
||||
{
|
||||
if (!strcmp(s, a->name))
|
||||
{
|
||||
Z_Free (a->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!a)
|
||||
{
|
||||
a = (cmdalias_t *) Z_Malloc (sizeof(cmdalias_t));
|
||||
a->next = cmd_alias;
|
||||
cmd_alias = a;
|
||||
}
|
||||
strcpy (a->name, s);
|
||||
|
||||
// copy the rest of the command line
|
||||
cmd[0] = 0; // start out with a null string
|
||||
c = Cmd_Argc();
|
||||
for (i = 2; i < c; i++)
|
||||
{
|
||||
q_strlcat (cmd, Cmd_Argv(i), sizeof(cmd));
|
||||
if (i != c - 1)
|
||||
q_strlcat (cmd, " ", sizeof(cmd));
|
||||
}
|
||||
if (q_strlcat(cmd, "\n", sizeof(cmd)) >= sizeof(cmd))
|
||||
{
|
||||
Con_Printf("alias value too long!\n");
|
||||
cmd[0] = '\n'; // nullify the string
|
||||
cmd[1] = 0;
|
||||
}
|
||||
|
||||
a->value = Z_Strdup (cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Cmd_Unalias_f -- johnfitz
|
||||
===============
|
||||
*/
|
||||
void Cmd_Unalias_f (void)
|
||||
{
|
||||
cmdalias_t *a, *prev;
|
||||
|
||||
switch (Cmd_Argc())
|
||||
{
|
||||
default:
|
||||
case 1:
|
||||
Con_Printf("unalias <name> : delete alias\n");
|
||||
break;
|
||||
case 2:
|
||||
prev = NULL;
|
||||
for (a = cmd_alias; a; a = a->next)
|
||||
{
|
||||
if (!strcmp(Cmd_Argv(1), a->name))
|
||||
{
|
||||
if (prev)
|
||||
prev->next = a->next;
|
||||
else
|
||||
cmd_alias = a->next;
|
||||
|
||||
Z_Free (a->value);
|
||||
Z_Free (a);
|
||||
return;
|
||||
}
|
||||
prev = a;
|
||||
}
|
||||
Con_Printf ("No alias named %s\n", Cmd_Argv(1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Cmd_Unaliasall_f -- johnfitz
|
||||
===============
|
||||
*/
|
||||
void Cmd_Unaliasall_f (void)
|
||||
{
|
||||
cmdalias_t *blah;
|
||||
|
||||
while (cmd_alias)
|
||||
{
|
||||
blah = cmd_alias->next;
|
||||
Z_Free(cmd_alias->value);
|
||||
Z_Free(cmd_alias);
|
||||
cmd_alias = blah;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
COMMAND EXECUTION
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
typedef struct cmd_function_s
|
||||
{
|
||||
struct cmd_function_s *next;
|
||||
const char *name;
|
||||
xcommand_t function;
|
||||
} cmd_function_t;
|
||||
|
||||
|
||||
#define MAX_ARGS 80
|
||||
|
||||
static int cmd_argc;
|
||||
static char *cmd_argv[MAX_ARGS];
|
||||
static char cmd_null_string[] = "";
|
||||
static const char *cmd_args = NULL;
|
||||
|
||||
cmd_source_t cmd_source;
|
||||
|
||||
//johnfitz -- better tab completion
|
||||
//static cmd_function_t *cmd_functions; // possible commands to execute
|
||||
cmd_function_t *cmd_functions; // possible commands to execute
|
||||
//johnfitz
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_List_f -- johnfitz
|
||||
============
|
||||
*/
|
||||
void Cmd_List_f (void)
|
||||
{
|
||||
cmd_function_t *cmd;
|
||||
const char *partial;
|
||||
int len, count;
|
||||
|
||||
if (Cmd_Argc() > 1)
|
||||
{
|
||||
partial = Cmd_Argv (1);
|
||||
len = Q_strlen(partial);
|
||||
}
|
||||
else
|
||||
{
|
||||
partial = NULL;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
count=0;
|
||||
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
|
||||
{
|
||||
if (partial && Q_strncmp (partial,cmd->name, len))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Con_SafePrintf (" %s\n", cmd->name);
|
||||
count++;
|
||||
}
|
||||
|
||||
Con_SafePrintf ("%i commands", count);
|
||||
if (partial)
|
||||
{
|
||||
Con_SafePrintf (" beginning with \"%s\"", partial);
|
||||
}
|
||||
Con_SafePrintf ("\n");
|
||||
}
|
||||
|
||||
static char *Cmd_TintSubstring(const char *in, const char *substr, char *out, size_t outsize)
|
||||
{
|
||||
int l;
|
||||
char *m;
|
||||
q_strlcpy(out, in, outsize);
|
||||
while ((m = q_strcasestr(out, substr)))
|
||||
{
|
||||
l = strlen(substr);
|
||||
while (l-->0)
|
||||
if (*m >= ' ' && *m < 127)
|
||||
*m++ |= 0x80;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_Apropos_f
|
||||
|
||||
scans through each command and cvar names+descriptions for the given substring
|
||||
we don't support descriptions, so this isn't really all that useful, but even without the sake of consistency it still combines cvars+commands under a single command.
|
||||
============
|
||||
*/
|
||||
void Cmd_Apropos_f(void)
|
||||
{
|
||||
char tmpbuf[256];
|
||||
int hits = 0;
|
||||
cmd_function_t *cmd;
|
||||
cvar_t *var;
|
||||
const char *substr = Cmd_Argv (1);
|
||||
if (!*substr)
|
||||
{
|
||||
Con_SafePrintf ("%s <substring> : search through commands and cvars for the given substring\n", Cmd_Argv(0));
|
||||
return;
|
||||
}
|
||||
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
|
||||
{
|
||||
if (q_strcasestr(cmd->name, substr))
|
||||
{
|
||||
hits++;
|
||||
Con_SafePrintf ("%s\n", Cmd_TintSubstring(cmd->name, substr, tmpbuf, sizeof(tmpbuf)));
|
||||
}
|
||||
}
|
||||
|
||||
// for (var=Cvar_FindVarAfter("", 0) ; var ; var=var->next)
|
||||
// {
|
||||
// if (q_strcasestr(var->name, substr))
|
||||
// {
|
||||
// hits++;
|
||||
// Con_SafePrintf ("%s (current value: \"%s\")\n", Cmd_TintSubstring(var->name, substr, tmpbuf, sizeof(tmpbuf)), var->string);
|
||||
// }
|
||||
// } // TODO:
|
||||
if (!hits)
|
||||
Con_SafePrintf ("no cvars nor commands contain that substring\n");
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_Init
|
||||
============
|
||||
*/
|
||||
void Cmd_Init (void)
|
||||
{
|
||||
Cmd_AddCommand ("cmdlist", Cmd_List_f); //johnfitz
|
||||
Cmd_AddCommand ("unalias", Cmd_Unalias_f); //johnfitz
|
||||
Cmd_AddCommand ("unaliasall", Cmd_Unaliasall_f); //johnfitz
|
||||
|
||||
Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f);
|
||||
Cmd_AddCommand ("exec",Cmd_Exec_f);
|
||||
Cmd_AddCommand ("echo",Cmd_Echo_f);
|
||||
Cmd_AddCommand ("alias",Cmd_Alias_f);
|
||||
Cmd_AddCommand ("cmd", Cmd_ForwardToServer);
|
||||
Cmd_AddCommand ("wait", Cmd_Wait_f);
|
||||
|
||||
Cmd_AddCommand ("apropos", Cmd_Apropos_f);
|
||||
Cmd_AddCommand ("find", Cmd_Apropos_f);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_Argc
|
||||
============
|
||||
*/
|
||||
int Cmd_Argc (void)
|
||||
{
|
||||
return cmd_argc;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_Argv
|
||||
============
|
||||
*/
|
||||
const char *Cmd_Argv (int arg)
|
||||
{
|
||||
if (arg < 0 || arg >= cmd_argc)
|
||||
return cmd_null_string;
|
||||
return cmd_argv[arg];
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_Args
|
||||
============
|
||||
*/
|
||||
const char *Cmd_Args (void)
|
||||
{
|
||||
return cmd_args;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_TokenizeString
|
||||
|
||||
Parses the given string into command line tokens.
|
||||
============
|
||||
*/
|
||||
void Cmd_TokenizeString (const char *text)
|
||||
{
|
||||
int i;
|
||||
|
||||
// clear the args from the last string
|
||||
for (i=0 ; i<cmd_argc ; i++)
|
||||
Z_Free (cmd_argv[i]);
|
||||
|
||||
cmd_argc = 0;
|
||||
cmd_args = NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
// skip whitespace up to a /n
|
||||
while (*text && *text <= ' ' && *text != '\n')
|
||||
{
|
||||
text++;
|
||||
}
|
||||
|
||||
if (*text == '\n')
|
||||
{ // a newline seperates commands in the buffer
|
||||
text++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!*text)
|
||||
return;
|
||||
|
||||
if (cmd_argc == 1)
|
||||
cmd_args = text;
|
||||
|
||||
text = COM_Parse (text);
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
if (cmd_argc < MAX_ARGS)
|
||||
{
|
||||
cmd_argv[cmd_argc] = Z_Strdup (com_token);
|
||||
cmd_argc++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_AddCommand
|
||||
============
|
||||
*/
|
||||
void Cmd_AddCommand (const char *cmd_name, xcommand_t function)
|
||||
{
|
||||
cmd_function_t *cmd;
|
||||
cmd_function_t *cursor,*prev; //johnfitz -- sorted list insert
|
||||
|
||||
if (host_initialized) // because hunk allocation would get stomped
|
||||
Sys_Error ("Cmd_AddCommand after host_initialized");
|
||||
|
||||
// fail if the command is a variable name
|
||||
if (Cvar_VariableString(cmd_name)[0])
|
||||
{
|
||||
Con_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
|
||||
return;
|
||||
}
|
||||
|
||||
// fail if the command already exists
|
||||
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
|
||||
{
|
||||
if (!Q_strcmp (cmd_name, cmd->name))
|
||||
{
|
||||
Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cmd = (cmd_function_t *) Hunk_Alloc (sizeof(cmd_function_t));
|
||||
cmd->name = cmd_name;
|
||||
cmd->function = function;
|
||||
|
||||
//johnfitz -- insert each entry in alphabetical order
|
||||
if (cmd_functions == NULL || strcmp(cmd->name, cmd_functions->name) < 0) //insert at front
|
||||
{
|
||||
cmd->next = cmd_functions;
|
||||
cmd_functions = cmd;
|
||||
}
|
||||
else //insert later
|
||||
{
|
||||
prev = cmd_functions;
|
||||
cursor = cmd_functions->next;
|
||||
while ((cursor != NULL) && (strcmp(cmd->name, cursor->name) > 0))
|
||||
{
|
||||
prev = cursor;
|
||||
cursor = cursor->next;
|
||||
}
|
||||
cmd->next = prev->next;
|
||||
prev->next = cmd;
|
||||
}
|
||||
//johnfitz
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_Exists
|
||||
============
|
||||
*/
|
||||
qboolean Cmd_Exists (const char *cmd_name)
|
||||
{
|
||||
cmd_function_t *cmd;
|
||||
|
||||
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
|
||||
{
|
||||
if (!Q_strcmp (cmd_name,cmd->name))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_CompleteCommand
|
||||
============
|
||||
*/
|
||||
const char *Cmd_CompleteCommand (const char *partial)
|
||||
{
|
||||
cmd_function_t *cmd;
|
||||
int len;
|
||||
|
||||
len = Q_strlen(partial);
|
||||
|
||||
if (!len)
|
||||
return NULL;
|
||||
|
||||
// check functions
|
||||
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
|
||||
if (!Q_strncmp (partial,cmd->name, len))
|
||||
return cmd->name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cmd_ExecuteString
|
||||
|
||||
A complete command line has been parsed, so try to execute it
|
||||
FIXME: lookupnoadd the token to speed search?
|
||||
============
|
||||
*/
|
||||
void Cmd_ExecuteString (const char *text, cmd_source_t src)
|
||||
{
|
||||
cmd_function_t *cmd;
|
||||
cmdalias_t *a;
|
||||
|
||||
cmd_source = src;
|
||||
Cmd_TokenizeString (text);
|
||||
|
||||
// execute the command line
|
||||
if (!Cmd_Argc())
|
||||
return; // no tokens
|
||||
|
||||
// check functions
|
||||
for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
|
||||
{
|
||||
if (!q_strcasecmp (cmd_argv[0],cmd->name))
|
||||
{
|
||||
cmd->function ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// check alias
|
||||
for (a=cmd_alias ; a ; a=a->next)
|
||||
{
|
||||
if (!q_strcasecmp (cmd_argv[0], a->name))
|
||||
{
|
||||
Cbuf_InsertText (a->value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// check cvars
|
||||
if (!Cvar_Command ())
|
||||
Con_Printf ("Unknown command \"%s\"\n", Cmd_Argv(0));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
Cmd_ForwardToServer
|
||||
|
||||
Sends the entire command line over to the server
|
||||
===================
|
||||
*/
|
||||
void Cmd_ForwardToServer (void)
|
||||
{
|
||||
if (cls.state != ca_connected)
|
||||
{
|
||||
Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cls.demoplayback)
|
||||
return; // not really connected
|
||||
|
||||
MSG_WriteByte (&cls.message, clc_stringcmd);
|
||||
if (q_strcasecmp(Cmd_Argv(0), "cmd") != 0)
|
||||
{
|
||||
SZ_Print (&cls.message, Cmd_Argv(0));
|
||||
SZ_Print (&cls.message, " ");
|
||||
}
|
||||
if (Cmd_Argc() > 1)
|
||||
SZ_Print (&cls.message, Cmd_Args());
|
||||
else
|
||||
SZ_Print (&cls.message, "\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Cmd_CheckParm
|
||||
|
||||
Returns the position (1 to argc-1) in the command's argument list
|
||||
where the given parameter apears, or 0 if not present
|
||||
================
|
||||
*/
|
||||
|
||||
int Cmd_CheckParm (const char *parm)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!parm)
|
||||
Sys_Error ("Cmd_CheckParm: null input\n");
|
||||
|
||||
for (i = 1; i < Cmd_Argc (); i++)
|
||||
if ( !q_strcasecmp (parm, Cmd_Argv (i)) )
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 _QUAKE_CMD_H
|
||||
#define _QUAKE_CMD_H
|
||||
|
||||
// cmd.h -- Command buffer and command execution
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*
|
||||
|
||||
Any number of commands can be added in a frame, from several different sources.
|
||||
Most commands come from either keybindings or console line input, but remote
|
||||
servers can also send across commands and entire text files can be execed.
|
||||
|
||||
The + command line options are also added to the command buffer.
|
||||
|
||||
The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute ();
|
||||
|
||||
*/
|
||||
|
||||
void Cbuf_Init (void);
|
||||
// allocates an initial text buffer that will grow as needed
|
||||
|
||||
void Cbuf_AddText (const char *text);
|
||||
// as new commands are generated from the console or keybindings,
|
||||
// the text is added to the end of the command buffer.
|
||||
|
||||
void Cbuf_InsertText (const char *text);
|
||||
// when a command wants to issue other commands immediately, the text is
|
||||
// inserted at the beginning of the buffer, before any remaining unexecuted
|
||||
// commands.
|
||||
|
||||
void Cbuf_Execute (void);
|
||||
// Pulls off \n terminated lines of text from the command buffer and sends
|
||||
// them through Cmd_ExecuteString. Stops when the buffer is empty.
|
||||
// Normally called once per frame, but may be explicitly invoked.
|
||||
// Do not call inside a command function!
|
||||
|
||||
//===========================================================================
|
||||
|
||||
/*
|
||||
|
||||
Command execution takes a null terminated string, breaks it into tokens,
|
||||
then searches for a command or variable that matches the first token.
|
||||
|
||||
Commands can come from three sources, but the handler functions may choose
|
||||
to dissallow the action or forward it to a remote server if the source is
|
||||
not apropriate.
|
||||
|
||||
*/
|
||||
|
||||
typedef void (*xcommand_t) (void);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
src_client, // came in over a net connection as a clc_stringcmd
|
||||
// host_client will be valid during this state.
|
||||
src_command // from the command buffer
|
||||
} cmd_source_t;
|
||||
|
||||
extern cmd_source_t cmd_source;
|
||||
|
||||
void Cmd_Init (void);
|
||||
|
||||
void Cmd_AddCommand (const char *cmd_name, xcommand_t function);
|
||||
// called by the init functions of other parts of the program to
|
||||
// register commands and functions to call for them.
|
||||
// The cmd_name is referenced later, so it should not be in temp memory
|
||||
|
||||
qboolean Cmd_Exists (const char *cmd_name);
|
||||
// used by the cvar code to check for cvar / command name overlap
|
||||
|
||||
const char *Cmd_CompleteCommand (const char *partial);
|
||||
// attempts to match a partial command for automatic command line completion
|
||||
// returns NULL if nothing fits
|
||||
|
||||
int Cmd_Argc (void);
|
||||
const char *Cmd_Argv (int arg);
|
||||
const char *Cmd_Args (void);
|
||||
// The functions that execute commands get their parameters with these
|
||||
// functions. Cmd_Argv () will return an empty string, not a NULL
|
||||
// if arg > argc, so string operations are allways safe.
|
||||
|
||||
int Cmd_CheckParm (const char *parm);
|
||||
// Returns the position (1 to argc-1) in the command's argument list
|
||||
// where the given parameter apears, or 0 if not present
|
||||
|
||||
void Cmd_TokenizeString (const char *text);
|
||||
// Takes a null terminated string. Does not need to be /n terminated.
|
||||
// breaks the string up into arg tokens.
|
||||
|
||||
void Cmd_ExecuteString (const char *text, cmd_source_t src);
|
||||
// Parses a single line of text into arguments and tries to execute it.
|
||||
// The text can come from the command buffer, a remote client, or stdin.
|
||||
|
||||
void Cmd_ForwardToServer (void);
|
||||
// adds the current command line as a clc_stringcmd to the client message.
|
||||
// things like godmode, noclip, etc, are commands directed to the server,
|
||||
// so when they are typed in at the console, they will need to be forwarded.
|
||||
|
||||
void Cmd_Print (const char *text);
|
||||
// used by command functions to send output to either the graphics console or
|
||||
// passed as a print message to the client
|
||||
|
||||
#endif /* _QUAKE_CMD_H */
|
||||
|
||||
+3022
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 _Q_COMMON_H
|
||||
#define _Q_COMMON_H
|
||||
|
||||
// comndef.h -- general definitions
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(disable:4244)
|
||||
/* 'argument' : conversion from 'type1' to 'type2',
|
||||
possible loss of data */
|
||||
# pragma warning(disable:4305)
|
||||
/* 'identifier' : truncation from 'type1' to 'type2' */
|
||||
/* in our case, truncation from 'double' to 'float' */
|
||||
# pragma warning(disable:4267)
|
||||
/* 'var' : conversion from 'size_t' to 'type',
|
||||
possible loss of data (/Wp64 warning) */
|
||||
#endif /* _MSC_VER */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L))
|
||||
#define GENERIC_TYPES(x, separator) \
|
||||
x(int, i) separator \
|
||||
x(unsigned int, u) separator \
|
||||
x(long, l) separator \
|
||||
x(unsigned long, ul) separator \
|
||||
x(long long, ll) separator \
|
||||
x(unsigned long long, ull) separator \
|
||||
x(float, f) separator \
|
||||
x(double, d)
|
||||
|
||||
#define COMMA ,
|
||||
#define NO_COMMA
|
||||
|
||||
#define IMPL_GENERIC_FUNCS(type, suffix) \
|
||||
static inline type q_min_##suffix (type a, type b) { \
|
||||
return (a < b) ? a : b; \
|
||||
} \
|
||||
static inline type q_max_##suffix (type a, type b) { \
|
||||
return (a > b) ? a : b; \
|
||||
} \
|
||||
static inline type clamp_##suffix (type minval, type val, type maxval) { \
|
||||
return (val < minval) ? minval : ((val > maxval) ? maxval : val); \
|
||||
}
|
||||
|
||||
GENERIC_TYPES (IMPL_GENERIC_FUNCS, NO_COMMA)
|
||||
|
||||
#define SELECT_Q_MIN(type, suffix) type: q_min_##suffix
|
||||
#define q_min(a, b) _Generic((a) + (b), GENERIC_TYPES (SELECT_Q_MIN, COMMA))(a, b)
|
||||
|
||||
#define SELECT_Q_MAX(type, suffix) type: q_max_##suffix
|
||||
#define q_max(a, b) _Generic((a) + (b), GENERIC_TYPES (SELECT_Q_MAX, COMMA))(a, b)
|
||||
|
||||
#define SELECT_CLAMP(type, suffix) type: clamp_##suffix
|
||||
#define CLAMP(minval, val, maxval) _Generic((minval) + (val) + (maxval), \
|
||||
GENERIC_TYPES (SELECT_CLAMP, COMMA))(minval, val, maxval)
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
/* min and max macros with type checking -- based on tyrquake. */
|
||||
#define q_max(a,b) ({ \
|
||||
const __typeof(a) a_ = (a); \
|
||||
const __typeof(b) b_ = (b); \
|
||||
(void)(&a_ == &b_); \
|
||||
(a_ > b_) ? a_ : b_; \
|
||||
})
|
||||
#define q_min(a,b) ({ \
|
||||
const __typeof(a) a_ = (a); \
|
||||
const __typeof(b) b_ = (b); \
|
||||
(void)(&a_ == &b_); \
|
||||
(a_ < b_) ? a_ : b_; \
|
||||
})
|
||||
#define CLAMP(_minval, x, _maxval) ({ \
|
||||
const __typeof(x) x_ = (x); \
|
||||
const __typeof(_minval) valmin_ = (_minval);\
|
||||
const __typeof(_maxval) valmax_ = (_maxval);\
|
||||
(void)(&x_ == &valmin_); \
|
||||
(void)(&x_ == &valmax_); \
|
||||
(x_ < valmin_) ? valmin_ : \
|
||||
(x_ > valmax_) ? valmax_ : x_; \
|
||||
})
|
||||
|
||||
#else
|
||||
#define q_min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define q_max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define CLAMP(_minval, x, _maxval) \
|
||||
((x) < (_minval) ? (_minval) : \
|
||||
(x) > (_maxval) ? (_maxval) : (x))
|
||||
#endif
|
||||
|
||||
typedef struct sizebuf_s
|
||||
{
|
||||
qboolean allowoverflow; // if false, do a Sys_Error
|
||||
qboolean overflowed; // set to true if the buffer size failed
|
||||
byte *data;
|
||||
int maxsize;
|
||||
int cursize;
|
||||
} sizebuf_t;
|
||||
|
||||
void SZ_Alloc (sizebuf_t *buf, int startsize);
|
||||
void SZ_Free (sizebuf_t *buf);
|
||||
void SZ_Clear (sizebuf_t *buf);
|
||||
void *SZ_GetSpace (sizebuf_t *buf, int length);
|
||||
void SZ_Write (sizebuf_t *buf, const void *data, int length);
|
||||
void SZ_Print (sizebuf_t *buf, const char *data); // strcats onto the sizebuf
|
||||
|
||||
//============================================================================
|
||||
|
||||
typedef struct link_s
|
||||
{
|
||||
struct link_s *prev, *next;
|
||||
} link_t;
|
||||
|
||||
|
||||
void ClearLink (link_t *l);
|
||||
void RemoveLink (link_t *l);
|
||||
void InsertLinkBefore (link_t *l, link_t *before);
|
||||
void InsertLinkAfter (link_t *l, link_t *after);
|
||||
|
||||
// (type *)STRUCT_FROM_LINK(link_t *link, type, member)
|
||||
// ent = STRUCT_FROM_LINK(link,entity_t,order)
|
||||
// FIXME: remove this mess!
|
||||
#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - offsetof(t,m)))
|
||||
|
||||
//============================================================================
|
||||
|
||||
typedef struct vec_header_t {
|
||||
size_t capacity;
|
||||
size_t size;
|
||||
} vec_header_t;
|
||||
|
||||
#define VEC_HEADER(v) (((vec_header_t*)(v))[-1])
|
||||
|
||||
#define VEC_PUSH(v,n) do { Vec_Grow((void**)&(v), sizeof((v)[0]), 1); (v)[VEC_HEADER(v).size++] = (n); } while (0)
|
||||
#define VEC_SIZE(v) ((v) ? VEC_HEADER(v).size : 0)
|
||||
#define VEC_FREE(v) Vec_Free((void**)&(v))
|
||||
#define VEC_CLEAR(v) Vec_Clear((void**)&(v))
|
||||
|
||||
void Vec_Grow (void **pvec, size_t element_size, size_t count);
|
||||
void Vec_Append (void **pvec, size_t element_size, const void *data, size_t count);
|
||||
void Vec_Clear (void **pvec);
|
||||
void Vec_Free (void **pvec);
|
||||
|
||||
//============================================================================
|
||||
|
||||
extern qboolean host_bigendian;
|
||||
|
||||
extern short (*BigShort) (short l);
|
||||
extern short (*LittleShort) (short l);
|
||||
extern int (*BigLong) (int l);
|
||||
extern int (*LittleLong) (int l);
|
||||
extern float (*BigFloat) (float l);
|
||||
extern float (*LittleFloat) (float l);
|
||||
|
||||
//============================================================================
|
||||
|
||||
void MSG_WriteChar (sizebuf_t *sb, int c);
|
||||
void MSG_WriteByte (sizebuf_t *sb, int c);
|
||||
void MSG_WriteShort (sizebuf_t *sb, int c);
|
||||
void MSG_WriteLong (sizebuf_t *sb, int c);
|
||||
void MSG_WriteFloat (sizebuf_t *sb, float f);
|
||||
void MSG_WriteString (sizebuf_t *sb, const char *s);
|
||||
void MSG_WriteCoord (sizebuf_t *sb, float f, unsigned int flags);
|
||||
void MSG_WriteAngle (sizebuf_t *sb, float f, unsigned int flags);
|
||||
void MSG_WriteAngle16 (sizebuf_t *sb, float f, unsigned int flags); //johnfitz
|
||||
|
||||
extern int msg_readcount;
|
||||
extern qboolean msg_badread; // set if a read goes beyond end of message
|
||||
|
||||
void MSG_BeginReading (void);
|
||||
int MSG_ReadChar (void);
|
||||
int MSG_ReadByte (void);
|
||||
int MSG_ReadShort (void);
|
||||
int MSG_ReadLong (void);
|
||||
float MSG_ReadFloat (void);
|
||||
const char *MSG_ReadString (void);
|
||||
|
||||
float MSG_ReadCoord (unsigned int flags);
|
||||
float MSG_ReadAngle (unsigned int flags);
|
||||
float MSG_ReadAngle16 (unsigned int flags); //johnfitz
|
||||
|
||||
//============================================================================
|
||||
|
||||
void Q_memset (void *dest, int fill, size_t count);
|
||||
void Q_memcpy (void *dest, const void *src, size_t count);
|
||||
int Q_memcmp (const void *m1, const void *m2, size_t count);
|
||||
void Q_strcpy (char *dest, const char *src);
|
||||
void Q_strncpy (char *dest, const char *src, int count);
|
||||
int Q_strlen (const char *str);
|
||||
char *Q_strrchr (const char *s, char c);
|
||||
void Q_strcat (char *dest, const char *src);
|
||||
int Q_strcmp (const char *s1, const char *s2);
|
||||
int Q_strncmp (const char *s1, const char *s2, int count);
|
||||
int Q_atoi (const char *str);
|
||||
float Q_atof (const char *str);
|
||||
|
||||
|
||||
#include "strl_fn.hpp"
|
||||
|
||||
/* locale-insensitive strcasecmp replacement functions: */
|
||||
extern int q_strcasecmp (const char * s1, const char * s2);
|
||||
extern int q_strncasecmp (const char *s1, const char *s2, size_t n);
|
||||
|
||||
/* locale-insensitive case-insensitive alternative to strstr */
|
||||
extern char *q_strcasestr(const char *haystack, const char *needle);
|
||||
|
||||
/* locale-insensitive strlwr/upr replacement functions: */
|
||||
extern char *q_strlwr (char *str);
|
||||
extern char *q_strupr (char *str);
|
||||
|
||||
/* snprintf, vsnprintf : always use our versions. */
|
||||
extern int q_snprintf (char *str, size_t size, const char *format, ...) FUNC_PRINTF(3,4);
|
||||
extern int q_vsnprintf(char *str, size_t size, const char *format, va_list args) FUNC_PRINTF(3,0);
|
||||
|
||||
//============================================================================
|
||||
|
||||
extern char com_token[1024];
|
||||
extern qboolean com_eof;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CPE_NOTRUNC, // return parse error in case of overflow
|
||||
CPE_ALLOWTRUNC // truncate com_token in case of overflow
|
||||
} cpe_mode;
|
||||
|
||||
const char *COM_Parse (const char *data);
|
||||
const char *COM_ParseEx (const char *data, cpe_mode mode);
|
||||
|
||||
|
||||
extern int com_argc;
|
||||
extern char **com_argv;
|
||||
|
||||
extern int safemode;
|
||||
/* safe mode: in true, the engine will behave as if one
|
||||
of these arguments were actually on the command line:
|
||||
-nosound, -nocdaudio, -nomidi, -stdvid, -dibonly,
|
||||
-nomouse, -nojoy, -nolan
|
||||
*/
|
||||
|
||||
int COM_CheckParm (const char *parm);
|
||||
|
||||
void COM_Init (void);
|
||||
void COM_InitArgv (int argc, char **argv);
|
||||
void COM_InitFilesystem (void);
|
||||
|
||||
const char *COM_SkipPath (const char *pathname);
|
||||
void COM_StripExtension (const char *in, char *out, size_t outsize);
|
||||
void COM_FileBase (const char *in, char *out, size_t outsize);
|
||||
void COM_AddExtension (char *path, const char *extension, size_t len);
|
||||
#if 0 /* COM_DefaultExtension can be dangerous */
|
||||
void COM_DefaultExtension (char *path, const char *extension, size_t len);
|
||||
#endif
|
||||
const char *COM_FileGetExtension (const char *in); /* doesn't return NULL */
|
||||
void COM_ExtractExtension (const char *in, char *out, size_t outsize);
|
||||
void COM_CreatePath (char *path);
|
||||
|
||||
char *va (const char *format, ...) FUNC_PRINTF(1,2);
|
||||
// does a varargs printf into a temp buffer
|
||||
|
||||
unsigned COM_HashString (const char *str);
|
||||
|
||||
// localization support for 2021 rerelease version:
|
||||
void LOC_Init (void);
|
||||
void LOC_Shutdown (void);
|
||||
const char* LOC_GetRawString (const char *key);
|
||||
const char* LOC_GetString (const char *key);
|
||||
qboolean LOC_HasPlaceholders (const char *str);
|
||||
size_t LOC_Format (const char *format, const char* (*getarg_fn)(int idx, void* userdata), void* userdata, char* out, size_t len);
|
||||
|
||||
//============================================================================
|
||||
|
||||
// QUAKEFS
|
||||
typedef struct
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
int filepos, filelen;
|
||||
} packfile_t;
|
||||
|
||||
typedef struct pack_s
|
||||
{
|
||||
char filename[MAX_OSPATH];
|
||||
int handle;
|
||||
int numfiles;
|
||||
packfile_t *files;
|
||||
} pack_t;
|
||||
|
||||
typedef struct searchpath_s
|
||||
{
|
||||
unsigned int path_id; // identifier assigned to the game directory
|
||||
// Note that <install_dir>/game1 and
|
||||
// <userdir>/game1 have the same id.
|
||||
char filename[MAX_OSPATH];
|
||||
pack_t *pack; // only one of filename / pack will be used
|
||||
struct searchpath_s *next;
|
||||
} searchpath_t;
|
||||
|
||||
extern searchpath_t *com_searchpaths;
|
||||
extern searchpath_t *com_base_searchpaths;
|
||||
|
||||
extern int com_filesize;
|
||||
struct cache_user_s;
|
||||
|
||||
extern char com_basedir[MAX_OSPATH];
|
||||
extern char com_gamedir[MAX_OSPATH];
|
||||
extern int file_from_pak; // global indicating that file came from a pak
|
||||
|
||||
void COM_WriteFile (const char *filename, const void *data, int len);
|
||||
int COM_OpenFile (const char *filename, int *handle, unsigned int *path_id);
|
||||
int COM_FOpenFile (const char *filename, FILE **file, unsigned int *path_id);
|
||||
qboolean COM_FileExists (const char *filename, unsigned int *path_id);
|
||||
void COM_CloseFile (int h);
|
||||
|
||||
// these procedures open a file using COM_FindFile and loads it into a proper
|
||||
// buffer. the buffer is allocated with a total size of com_filesize + 1. the
|
||||
// procedures differ by their buffer allocation method.
|
||||
byte *COM_LoadStackFile (const char *path, void *buffer, int bufsize,
|
||||
unsigned int *path_id);
|
||||
// uses the specified stack stack buffer with the specified size
|
||||
// of bufsize. if bufsize is too short, uses temp hunk. the bufsize
|
||||
// must include the +1
|
||||
byte *COM_LoadTempFile (const char *path, unsigned int *path_id);
|
||||
// allocates the buffer on the temp hunk.
|
||||
byte *COM_LoadHunkFile (const char *path, unsigned int *path_id);
|
||||
// allocates the buffer on the hunk.
|
||||
byte *COM_LoadZoneFile (const char *path, unsigned int *path_id);
|
||||
// allocates the buffer on the zone.
|
||||
void COM_LoadCacheFile (const char *path, struct cache_user_s *cu,
|
||||
unsigned int *path_id);
|
||||
// uses cache mem for allocating the buffer.
|
||||
byte *COM_LoadMallocFile (const char *path, unsigned int *path_id);
|
||||
// allocates the buffer on the system mem (malloc).
|
||||
|
||||
// Opens the given path directly, ignoring search paths.
|
||||
// Returns NULL on failure, or else a '\0'-terminated malloc'ed buffer.
|
||||
// Loads in "t" mode so CRLF to LF translation is performed on Windows.
|
||||
byte *COM_LoadMallocFile_TextMode_OSPath (const char *path, long *len_out);
|
||||
|
||||
// Attempts to parse an int, followed by a newline.
|
||||
// Returns advanced buffer position.
|
||||
// Doesn't signal parsing failure, but this is not needed for savegame loading.
|
||||
const char *COM_ParseIntNewline(const char *buffer, int *value);
|
||||
|
||||
// Attempts to parse a float followed by a newline.
|
||||
// Returns advanced buffer position.
|
||||
const char *COM_ParseFloatNewline(const char *buffer, float *value);
|
||||
|
||||
// Parse a string of non-whitespace into com_token, then tries to consume a
|
||||
// newline. Returns advanced buffer position.
|
||||
const char *COM_ParseStringNewline(const char *buffer);
|
||||
|
||||
|
||||
#define FS_ENT_NONE (0)
|
||||
#define FS_ENT_FILE (1 << 0)
|
||||
#define FS_ENT_DIRECTORY (1 << 1)
|
||||
|
||||
/* The following FS_*() stdio replacements are necessary if one is
|
||||
* to perform non-sequential reads on files reopened on pak files
|
||||
* because we need the bookkeeping about file start/end positions.
|
||||
* Allocating and filling in the fshandle_t structure is the users'
|
||||
* responsibility when the file is initially opened. */
|
||||
|
||||
typedef struct _fshandle_t
|
||||
{
|
||||
FILE *file;
|
||||
qboolean pak; /* is the file read from a pak */
|
||||
long start; /* file or data start position */
|
||||
long length; /* file or data size */
|
||||
long pos; /* current position relative to start */
|
||||
} fshandle_t;
|
||||
|
||||
size_t FS_fread(void *ptr, size_t size, size_t nmemb, fshandle_t *fh);
|
||||
int FS_fseek(fshandle_t *fh, long offset, int whence);
|
||||
long FS_ftell(fshandle_t *fh);
|
||||
void FS_rewind(fshandle_t *fh);
|
||||
int FS_feof(fshandle_t *fh);
|
||||
int FS_ferror(fshandle_t *fh);
|
||||
int FS_fclose(fshandle_t *fh);
|
||||
int FS_fgetc(fshandle_t *fh);
|
||||
char *FS_fgets(char *s, int size, fshandle_t *fh);
|
||||
long FS_filelength (fshandle_t *fh);
|
||||
|
||||
|
||||
extern struct cvar_s registered;
|
||||
extern qboolean standard_quake, rogue, hipnotic;
|
||||
extern qboolean fitzmode;
|
||||
/* if true, run in fitzquake mode disabling custom quakespasm hacks */
|
||||
|
||||
#endif /* _Q_COMMON_H */
|
||||
|
||||
+1315
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 __CONSOLE_H
|
||||
#define __CONSOLE_H
|
||||
|
||||
//
|
||||
// console
|
||||
//
|
||||
extern int con_totallines;
|
||||
extern int con_backscroll;
|
||||
extern qboolean con_forcedup; // because no entities to refresh
|
||||
extern qboolean con_initialized;
|
||||
extern byte *con_chars;
|
||||
|
||||
extern char con_lastcenterstring[]; //johnfitz
|
||||
|
||||
void Con_DrawCharacter (int cx, int line, int num);
|
||||
|
||||
void Con_CheckResize (void);
|
||||
void Con_Init (void);
|
||||
void Con_DrawConsole (int lines, qboolean drawinput);
|
||||
void Con_Printf (const char *fmt, ...) FUNC_PRINTF(1,2);
|
||||
void Con_DWarning (const char *fmt, ...) FUNC_PRINTF(1,2); //ericw
|
||||
void Con_Warning (const char *fmt, ...) FUNC_PRINTF(1,2); //johnfitz
|
||||
void Con_DPrintf (const char *fmt, ...) FUNC_PRINTF(1,2);
|
||||
void Con_DPrintf2 (const char *fmt, ...) FUNC_PRINTF(1,2); //johnfitz
|
||||
void Con_SafePrintf (const char *fmt, ...) FUNC_PRINTF(1,2);
|
||||
void Con_DrawNotify (void);
|
||||
void Con_ClearNotify (void);
|
||||
void Con_ToggleConsole_f (void);
|
||||
|
||||
void Con_NotifyBox (const char *text); // during startup for sound / cd warnings
|
||||
|
||||
void Con_Show (void);
|
||||
void Con_Hide (void);
|
||||
|
||||
const char *Con_Quakebar (int len);
|
||||
void Con_TabComplete (void);
|
||||
void Con_LogCenterPrint (const char *str);
|
||||
|
||||
//
|
||||
// debuglog
|
||||
//
|
||||
void LOG_Init (quakeparms_t *parms);
|
||||
void LOG_Close (void);
|
||||
void Con_DebugLog (const char *msg);
|
||||
|
||||
#endif /* __CONSOLE_H */
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
/* crc.c */
|
||||
|
||||
#include "quakedef.hpp"
|
||||
#include "crc.hpp"
|
||||
|
||||
// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
|
||||
// and the initial and final xor values shown below... in other words, the
|
||||
// CCITT standard CRC used by XMODEM
|
||||
|
||||
#define CRC_INIT_VALUE 0xffff
|
||||
#define CRC_XOR_VALUE 0x0000
|
||||
|
||||
static const unsigned short crctable[256] =
|
||||
{
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
|
||||
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
|
||||
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
|
||||
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
|
||||
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
|
||||
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
|
||||
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
|
||||
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
|
||||
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
|
||||
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||
};
|
||||
|
||||
void CRC_Init(unsigned short *crcvalue)
|
||||
{
|
||||
*crcvalue = CRC_INIT_VALUE;
|
||||
}
|
||||
|
||||
void CRC_ProcessByte(unsigned short *crcvalue, byte data)
|
||||
{
|
||||
*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
|
||||
}
|
||||
|
||||
unsigned short CRC_Value(unsigned short crcvalue)
|
||||
{
|
||||
return crcvalue ^ CRC_XOR_VALUE;
|
||||
}
|
||||
|
||||
//johnfitz -- texture crc
|
||||
unsigned short CRC_Block (const byte *start, int count)
|
||||
{
|
||||
unsigned short crc;
|
||||
|
||||
CRC_Init (&crc);
|
||||
while (count--)
|
||||
crc = (crc << 8) ^ crctable[(crc >> 8) ^ *start++];
|
||||
|
||||
return crc;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
|
||||
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 _QUAKE_CRC_H
|
||||
#define _QUAKE_CRC_H
|
||||
|
||||
/* crc.h */
|
||||
|
||||
void CRC_Init(unsigned short *crcvalue);
|
||||
void CRC_ProcessByte(unsigned short *crcvalue, byte data);
|
||||
unsigned short CRC_Value(unsigned short crcvalue);
|
||||
unsigned short CRC_Block (const byte *start, int count); //johnfitz -- texture crc
|
||||
|
||||
#endif /* _QUAKE_CRC_H */
|
||||
|
||||
+560
@@ -0,0 +1,560 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// cvar.c -- dynamic variable tracking
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <ranges>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
|
||||
static cvar_t *cvar_vars;
|
||||
static char cvar_null_string[] = "";
|
||||
|
||||
std::map<std::string, cvar_t* > CLIENT_VARIABLES{};
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// USER COMMANDS
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
void Cvar_Reset(const std::string &name); //johnfitz
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_List_f -- johnfitz
|
||||
============
|
||||
*/
|
||||
void Cvar_List_f() {
|
||||
cvar_t *cvar;
|
||||
const char *partial;
|
||||
int len, count;
|
||||
|
||||
if (Cmd_Argc() > 1) {
|
||||
partial = Cmd_Argv(1);
|
||||
len = Q_strlen(partial);
|
||||
} else {
|
||||
partial = NULL;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
for (const auto &[name, var]: CLIENT_VARIABLES) {
|
||||
if (partial && Q_strncmp(partial, name.c_str(), len)) {
|
||||
continue;
|
||||
}
|
||||
Con_SafePrintf("%s%s %s \"%s\"\n",
|
||||
(var->flags & CVAR_ARCHIVE) ? "*" : " ",
|
||||
(var->flags & CVAR_NOTIFY) ? "s" : " ",
|
||||
name.c_str(),
|
||||
var->string);
|
||||
count++;
|
||||
}
|
||||
|
||||
Con_SafePrintf("%i cvars", count);
|
||||
if (partial) {
|
||||
Con_SafePrintf(" beginning with \"%s\"", partial);
|
||||
}
|
||||
Con_SafePrintf("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_Inc_f -- johnfitz
|
||||
============
|
||||
*/
|
||||
void Cvar_Inc_f(void) {
|
||||
switch (Cmd_Argc()) {
|
||||
default:
|
||||
case 1:
|
||||
Con_Printf("inc <cvar> [amount] : increment cvar\n");
|
||||
break;
|
||||
case 2:
|
||||
Cvar_SetValue(Cmd_Argv(1), Cvar_VariableValue(Cmd_Argv(1)) + 1);
|
||||
break;
|
||||
case 3:
|
||||
Cvar_SetValue(Cmd_Argv(1), Cvar_VariableValue(Cmd_Argv(1)) + Q_atof(Cmd_Argv(2)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_Toggle_f -- johnfitz
|
||||
============
|
||||
*/
|
||||
void Cvar_Toggle_f(void) {
|
||||
switch (Cmd_Argc()) {
|
||||
default:
|
||||
case 1:
|
||||
Con_Printf("toggle <cvar> : toggle cvar\n");
|
||||
break;
|
||||
case 2:
|
||||
if (Cvar_VariableValue(Cmd_Argv(1)))
|
||||
Cvar_Set(Cmd_Argv(1), "0");
|
||||
else
|
||||
Cvar_Set(Cmd_Argv(1), "1");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_Cycle_f -- johnfitz
|
||||
============
|
||||
*/
|
||||
void Cvar_Cycle_f() {
|
||||
int i;
|
||||
|
||||
if (Cmd_Argc() < 3) {
|
||||
Con_Printf("cycle <cvar> <value list>: cycle cvar through a list of values\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//loop through the args until you find one that matches the current cvar value.
|
||||
//yes, this will get stuck on a list that contains the same value twice.
|
||||
//it's not worth dealing with, and i'm not even sure it can be dealt with.
|
||||
for (i = 2; i < Cmd_Argc(); i++) {
|
||||
//zero is assumed to be a string, even though it could actually be zero. The worst case
|
||||
//is that the first time you call this command, it won't match on zero when it should, but after that,
|
||||
//it will be comparing strings that all had the same source (the user) so it will work.
|
||||
if (Q_atof(Cmd_Argv(i)) == 0) {
|
||||
if (!strcmp(Cmd_Argv(i), Cvar_VariableString(Cmd_Argv(1))))
|
||||
break;
|
||||
} else {
|
||||
if (Q_atof(Cmd_Argv(i)) == Cvar_VariableValue(Cmd_Argv(1)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == Cmd_Argc())
|
||||
Cvar_Set(Cmd_Argv(1), Cmd_Argv(2)); // no match
|
||||
else if (i + 1 == Cmd_Argc())
|
||||
Cvar_Set(Cmd_Argv(1), Cmd_Argv(2)); // matched last value in list
|
||||
else
|
||||
Cvar_Set(Cmd_Argv(1), Cmd_Argv(i + 1)); // matched earlier in list
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_Reset_f -- johnfitz
|
||||
============
|
||||
*/
|
||||
void Cvar_Reset_f() {
|
||||
switch (Cmd_Argc()) {
|
||||
default:
|
||||
case 1:
|
||||
Con_Printf("reset <cvar> : reset cvar to default\n");
|
||||
break;
|
||||
case 2:
|
||||
Cvar_Reset(Cmd_Argv(1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_ResetAll_f -- johnfitz
|
||||
============
|
||||
*/
|
||||
void Cvar_ResetAll_f(void) {
|
||||
cvar_t *var;
|
||||
|
||||
for (auto name: std::views::keys(CLIENT_VARIABLES))
|
||||
Cvar_Reset(name);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_ResetCfg_f -- QuakeSpasm
|
||||
============
|
||||
*/
|
||||
void Cvar_ResetCfg_f() {
|
||||
for (const auto &var: std::views::values(CLIENT_VARIABLES))
|
||||
if (var->flags & CVAR_ARCHIVE) Cvar_Reset(var->name);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// INIT
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_Init -- johnfitz
|
||||
============
|
||||
*/
|
||||
|
||||
void Cvar_Init() {
|
||||
Cmd_AddCommand("cvarlist", Cvar_List_f);
|
||||
Cmd_AddCommand("toggle", Cvar_Toggle_f);
|
||||
Cmd_AddCommand("cycle", Cvar_Cycle_f);
|
||||
Cmd_AddCommand("inc", Cvar_Inc_f);
|
||||
Cmd_AddCommand("reset", Cvar_Reset_f);
|
||||
Cmd_AddCommand("resetall", Cvar_ResetAll_f);
|
||||
Cmd_AddCommand("resetcfg", Cvar_ResetCfg_f);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// CVAR FUNCTIONS
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_FindVar
|
||||
============
|
||||
*/
|
||||
std::optional<cvar_t *> Cvar_FindVar(const std::string &desired) {
|
||||
for (auto &[name, var]: CLIENT_VARIABLES) {
|
||||
if (name == desired)
|
||||
return var;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
cvar_t *Cvar_FindVarAfter(const char *prev_name, unsigned int with_flags) {
|
||||
// cvar_t *var;
|
||||
//
|
||||
// if (*prev_name)
|
||||
// {
|
||||
// var = Cvar_FindVar (prev_name);
|
||||
// if (!var)
|
||||
// return NULL;
|
||||
// var = var->next;
|
||||
// }
|
||||
// else
|
||||
// var = cvar_vars;
|
||||
//
|
||||
// // search for the next cvar matching the needed flags
|
||||
// while (var)
|
||||
// {
|
||||
// if ((var->flags & with_flags) || !with_flags)
|
||||
// break;
|
||||
// var = var->next;
|
||||
// }
|
||||
// return var;
|
||||
return nullptr; // TODO
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_LockVar
|
||||
============
|
||||
*/
|
||||
void Cvar_LockVar(const std::string &name) {
|
||||
if (const auto var = Cvar_FindVar(name); var.has_value())
|
||||
var.value()->flags |= CVAR_LOCKED;
|
||||
}
|
||||
|
||||
void Cvar_UnlockVar(const std::string &name) {
|
||||
if (const auto var = Cvar_FindVar(name); var.has_value())
|
||||
var.value()->flags &= ~CVAR_LOCKED;
|
||||
}
|
||||
|
||||
void Cvar_UnlockAll() {
|
||||
for (const auto &var: std::views::values(CLIENT_VARIABLES)) {
|
||||
var->flags &= ~CVAR_LOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_VariableValue
|
||||
============
|
||||
*/
|
||||
float Cvar_VariableValue(const char *var_name) {
|
||||
const auto var = Cvar_FindVar(var_name);
|
||||
if (!var.has_value())
|
||||
return 0;
|
||||
return std::strtof(var.value()->string, nullptr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_VariableString
|
||||
============
|
||||
*/
|
||||
const char *Cvar_VariableString(const char *var_name) {
|
||||
const auto var = Cvar_FindVar(var_name);
|
||||
if (!var.has_value())
|
||||
return cvar_null_string;
|
||||
return var.value()->string;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_CompleteVariable
|
||||
============
|
||||
*/
|
||||
std::optional<std::string_view> Cvar_CompleteVariable(const std::string_view &partial) {
|
||||
if (!partial.empty())
|
||||
return std::nullopt;
|
||||
|
||||
// check functions
|
||||
for (const auto &name: CLIENT_VARIABLES | std::views::keys) {
|
||||
if (name.contains(name))
|
||||
return name;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_Reset -- johnfitz
|
||||
============
|
||||
*/
|
||||
void Cvar_Reset(const std::string &name) {
|
||||
if (const auto var = Cvar_FindVar(name); !var.has_value())
|
||||
Con_Printf("variable \"%s\" not found\n", name.c_str());
|
||||
else
|
||||
Cvar_SetQuick(var.value(), var.value()->default_string);
|
||||
}
|
||||
|
||||
void Cvar_SetQuick(cvar_t *var, const std::string &value) {
|
||||
if (var->flags & (CVAR_ROM | CVAR_LOCKED))
|
||||
return;
|
||||
if (!(var->flags & CVAR_REGISTERED))
|
||||
return;
|
||||
|
||||
if (!var->string)
|
||||
var->string = Z_Strdup(value.c_str());
|
||||
else {
|
||||
int len;
|
||||
|
||||
if (!strcmp(var->string, value.c_str()))
|
||||
return; // no change
|
||||
|
||||
var->flags |= CVAR_CHANGED;
|
||||
len = value.length();
|
||||
if (len != Q_strlen(var->string)) {
|
||||
Z_Free((void *) var->string);
|
||||
var->string = (char *) Z_Malloc(len + 1);
|
||||
}
|
||||
memcpy((char *) var->string, value.c_str(), len + 1);
|
||||
}
|
||||
|
||||
var->value = Q_atof(var->string);
|
||||
|
||||
//johnfitz -- save initial value for "reset" command
|
||||
if (!var->default_string)
|
||||
var->default_string = Z_Strdup(var->string);
|
||||
//johnfitz -- during initialization, update default too
|
||||
else if (!host_initialized) {
|
||||
// Sys_Printf("changing default of %s: %s -> %s\n",
|
||||
// var->name, var->default_string, var->string);
|
||||
Z_Free((void *) var->default_string);
|
||||
var->default_string = Z_Strdup(var->string);
|
||||
}
|
||||
//johnfitz
|
||||
|
||||
if (var->callback)
|
||||
var->callback(var);
|
||||
}
|
||||
|
||||
void Cvar_SetValueQuick(cvar_t *var, const float value) {
|
||||
char val[32], *ptr = val;
|
||||
|
||||
if (value == (float) ((int) value))
|
||||
q_snprintf(val, sizeof(val), "%i", (int) value);
|
||||
else {
|
||||
q_snprintf(val, sizeof(val), "%f", value);
|
||||
// kill trailing zeroes
|
||||
while (*ptr)
|
||||
ptr++;
|
||||
while (--ptr > val && *ptr == '0' && ptr[-1] != '.')
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
Cvar_SetQuick(var, val);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_Set
|
||||
============
|
||||
*/
|
||||
void Cvar_Set(const std::string &name, const std::string &value) {
|
||||
auto var = Cvar_FindVar(name);
|
||||
if (!var.has_value()) {
|
||||
// there is an error in C code if this happens
|
||||
Con_Printf("Cvar_Set: variable %s not found\n", name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
Cvar_SetQuick(var.value(), value);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_SetValue
|
||||
============
|
||||
*/
|
||||
void Cvar_SetValue(const char *var_name, const float value) {
|
||||
char val[32], *ptr = val;
|
||||
|
||||
if (value == (float) ((int) value))
|
||||
q_snprintf(val, sizeof(val), "%i", (int) value);
|
||||
else {
|
||||
q_snprintf(val, sizeof(val), "%f", value);
|
||||
// kill trailing zeroes
|
||||
while (*ptr)
|
||||
ptr++;
|
||||
while (--ptr > val && *ptr == '0' && ptr[-1] != '.')
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
Cvar_Set(var_name, val);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_SetROM
|
||||
============
|
||||
*/
|
||||
void Cvar_SetROM(const char *var_name, const char *value) {
|
||||
if (const auto var = Cvar_FindVar(var_name); var.has_value()) {
|
||||
var.value()->flags &= ~CVAR_ROM;
|
||||
Cvar_SetQuick(var.value(), value);
|
||||
var.value()->flags |= CVAR_ROM;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_SetValueROM
|
||||
============
|
||||
*/
|
||||
void Cvar_SetValueROM(const char *var_name, const float value) {
|
||||
if (const auto var = Cvar_FindVar(var_name); var.has_value()) {
|
||||
var.value()->flags &= ~CVAR_ROM;
|
||||
Cvar_SetValueQuick(var.value(), value);
|
||||
var.value()->flags |= CVAR_ROM;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_RegisterVariable
|
||||
|
||||
Adds a freestanding variable to the variable list.
|
||||
============
|
||||
*/
|
||||
void Cvar_RegisterVariable(cvar_t *variable) {
|
||||
char value[512];
|
||||
qboolean set_rom;
|
||||
cvar_t *cursor, *prev; //johnfitz -- sorted list insert
|
||||
|
||||
// first check to see if it has already been defined
|
||||
if (Cvar_FindVar(variable->name)) {
|
||||
Con_Printf("Can't register variable %s, already defined\n", variable->name);
|
||||
return;
|
||||
}
|
||||
|
||||
// check for overlap with a command
|
||||
if (Cmd_Exists(variable->name)) {
|
||||
Con_Printf("Cvar_RegisterVariable: %s is a command\n", variable->name);
|
||||
return;
|
||||
}
|
||||
|
||||
CLIENT_VARIABLES.emplace(std::string(variable->name), variable);
|
||||
|
||||
//johnfitz
|
||||
variable->flags |= CVAR_REGISTERED;
|
||||
|
||||
// copy the value off, because future sets will Z_Free it
|
||||
std::strncpy(value, variable->string, sizeof(value));
|
||||
variable->string = NULL;
|
||||
variable->default_string = NULL;
|
||||
|
||||
if (!(variable->flags & CVAR_CALLBACK))
|
||||
variable->callback = NULL;
|
||||
|
||||
// set it through the function to be consistent
|
||||
set_rom = (variable->flags & CVAR_ROM);
|
||||
variable->flags &= ~CVAR_ROM;
|
||||
Cvar_SetQuick(variable, value);
|
||||
if (set_rom)
|
||||
variable->flags |= CVAR_ROM;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_SetCallback
|
||||
|
||||
Set a callback function to the var
|
||||
============
|
||||
*/
|
||||
void Cvar_SetCallback(cvar_t *var, cvarcallback_t func) {
|
||||
var->callback = func;
|
||||
if (func)
|
||||
var->flags |= CVAR_CALLBACK;
|
||||
else var->flags &= ~CVAR_CALLBACK;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_Command
|
||||
|
||||
Handles variable inspection and changing from the console
|
||||
============
|
||||
*/
|
||||
qboolean Cvar_Command() {
|
||||
// check variables
|
||||
auto var = Cvar_FindVar(Cmd_Argv(0));
|
||||
if (!var.has_value())
|
||||
return false;
|
||||
|
||||
// perform a variable print or set
|
||||
if (Cmd_Argc() == 1) {
|
||||
Con_Printf("\"%s\" is \"%s\"\n", var.value()->name, var.value()->string);
|
||||
return true;
|
||||
}
|
||||
|
||||
Cvar_Set(var.value()->name, Cmd_Argv(1));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
Cvar_WriteVariables
|
||||
|
||||
Writes lines containing "set variable value" for all variables
|
||||
with the archive flag set to true.
|
||||
============
|
||||
*/
|
||||
void Cvar_WriteVariables(FILE *f) {
|
||||
for (const auto &[name, var] : CLIENT_VARIABLES) {
|
||||
if (var->flags & CVAR_ARCHIVE)
|
||||
fprintf(f, "%s \"%s\"\n", name.c_str(), var->string);
|
||||
}
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 __CVAR_H__
|
||||
#define __CVAR_H__
|
||||
|
||||
/*
|
||||
cvar_t variables are used to hold scalar or string variables that can
|
||||
be changed or displayed at the console or prog code as well as accessed
|
||||
directly in C code.
|
||||
|
||||
it is sufficient to initialize a cvar_t with just the first two fields,
|
||||
or you can add a ,true flag for variables that you want saved to the
|
||||
configuration file when the game is quit:
|
||||
|
||||
cvar_t r_draworder = {"r_draworder","1"};
|
||||
cvar_t scr_screensize = {"screensize","1",true};
|
||||
|
||||
Cvars must be registered before use, or they will have a 0 value instead
|
||||
of the float interpretation of the string.
|
||||
Generally, all cvar_t declarations should be registered in the apropriate
|
||||
init function before any console commands are executed:
|
||||
|
||||
Cvar_RegisterVariable (&host_framerate);
|
||||
|
||||
|
||||
C code usually just references a cvar in place:
|
||||
if ( r_draworder.value )
|
||||
|
||||
It could optionally ask for the value to be looked up for a string name:
|
||||
if (Cvar_VariableValue ("r_draworder"))
|
||||
|
||||
Interpreted prog code can access cvars with the cvar(name) or
|
||||
cvar_set (name, value) internal functions:
|
||||
teamplay = cvar("teamplay");
|
||||
cvar_set ("registered", "1");
|
||||
|
||||
The user can access cvars from the console in two ways:
|
||||
r_draworder prints the current value
|
||||
r_draworder 0 sets the current value to 0
|
||||
|
||||
Cvars are restricted from having the same names as commands to keep this
|
||||
interface from being ambiguous.
|
||||
|
||||
*/
|
||||
|
||||
#define CVAR_NONE 0
|
||||
#define CVAR_ARCHIVE (1U << 0) // if set, causes it to be saved to config
|
||||
#define CVAR_NOTIFY (1U << 1) // changes will be broadcasted to all players (q1)
|
||||
#define CVAR_SERVERINFO (1U << 2) // added to serverinfo will be sent to clients (q1/net_dgrm.c and qwsv)
|
||||
#define CVAR_USERINFO (1U << 3) // added to userinfo, will be sent to server (qwcl)
|
||||
#define CVAR_CHANGED (1U << 4)
|
||||
#define CVAR_ROM (1U << 6)
|
||||
#define CVAR_LOCKED (1U << 8) // locked temporarily
|
||||
#define CVAR_REGISTERED (1U << 10) // the var is added to the list of variables
|
||||
#define CVAR_CALLBACK (1U << 16) // var has a callback
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
typedef void (*cvarcallback_t) (struct cvar_s *);
|
||||
|
||||
typedef struct cvar_s
|
||||
{
|
||||
const char *name;
|
||||
const char *string;
|
||||
unsigned int flags;
|
||||
float value;
|
||||
const char *default_string; //johnfitz -- remember defaults for reset function
|
||||
cvarcallback_t callback;
|
||||
} cvar_t;
|
||||
|
||||
void Cvar_RegisterVariable (cvar_t *variable);
|
||||
// registers a cvar that already has the name, string, and optionally
|
||||
// the archive elements set.
|
||||
|
||||
void Cvar_SetCallback (cvar_t *var, cvarcallback_t func);
|
||||
// set a callback function to the var
|
||||
|
||||
void Cvar_Set(const std::string &name, const std::string &value);
|
||||
// equivelant to "<name> <variable>" typed at the console
|
||||
|
||||
void Cvar_SetValue (const char *var_name, const float value);
|
||||
// expands value to a string and calls Cvar_Set
|
||||
|
||||
void Cvar_SetROM (const char *var_name, const char *value);
|
||||
void Cvar_SetValueROM (const char *var_name, const float value);
|
||||
// sets a CVAR_ROM variable from within the engine
|
||||
|
||||
void Cvar_SetQuick(cvar_t *var, const std::string &value);
|
||||
void Cvar_SetValueQuick (cvar_t *var, const float value);
|
||||
// these two accept a cvar pointer instead of a var name,
|
||||
// but are otherwise identical to the "non-Quick" versions.
|
||||
// the cvar MUST be registered.
|
||||
|
||||
float Cvar_VariableValue (const char *var_name);
|
||||
// returns 0 if not defined or non numeric
|
||||
|
||||
const char *Cvar_VariableString (const char *var_name);
|
||||
// returns an empty string if not defined
|
||||
|
||||
qboolean Cvar_Command (void);
|
||||
// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known
|
||||
// command. Returns true if the command was a variable reference that
|
||||
// was handled. (print or change)
|
||||
|
||||
void Cvar_WriteVariables (FILE *f);
|
||||
// Writes lines containing "set variable value" for all variables
|
||||
// with the CVAR_ARCHIVE flag set
|
||||
|
||||
std::optional<cvar_t*> Cvar_FindVar (const std::string &desired);
|
||||
cvar_t *Cvar_FindVarAfter (const char *prev_name, unsigned int with_flags);
|
||||
|
||||
void Cvar_LockVar(const std::string &name);
|
||||
void Cvar_UnlockVar(const std::string &name);
|
||||
void Cvar_UnlockAll (void);
|
||||
|
||||
void Cvar_Init (void);
|
||||
|
||||
const char *Cvar_CompleteVariable (const char *partial);
|
||||
// attempts to match a partial variable name for command line completion
|
||||
// returns NULL if nothing fits
|
||||
|
||||
extern std::map<std::string, cvar_t* > CLIENT_VARIABLES;
|
||||
|
||||
#endif /* __CVAR_H__ */
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// keep in sync with Misc/qs_pak/default.cfg
|
||||
|
||||
static const char default_cfg[] =
|
||||
"unbindall\n"
|
||||
|
||||
"bind ALT +strafe\n"
|
||||
|
||||
"bind , +moveleft\n"
|
||||
"bind a +moveleft\n"
|
||||
"bind . +moveright\n"
|
||||
"bind d +moveright\n"
|
||||
"bind DEL +lookdown\n"
|
||||
"bind PGDN +lookup\n"
|
||||
"bind END centerview\n"
|
||||
|
||||
"bind e +moveup\n"
|
||||
"bind c +movedown\n"
|
||||
"bind SHIFT +speed\n"
|
||||
"bind CTRL +attack\n"
|
||||
"bind UPARROW +forward\n"
|
||||
"bind w +forward\n"
|
||||
"bind DOWNARROW +back\n"
|
||||
"bind s +back\n"
|
||||
"bind LEFTARROW +left\n"
|
||||
"bind RIGHTARROW +right\n"
|
||||
|
||||
"bind SPACE +jump\n"
|
||||
|
||||
"bind TAB +showscores\n"
|
||||
|
||||
"bind 1 \"impulse 1\"\n"
|
||||
"bind 2 \"impulse 2\"\n"
|
||||
"bind 3 \"impulse 3\"\n"
|
||||
"bind 4 \"impulse 4\"\n"
|
||||
"bind 5 \"impulse 5\"\n"
|
||||
"bind 6 \"impulse 6\"\n"
|
||||
"bind 7 \"impulse 7\"\n"
|
||||
"bind 8 \"impulse 8\"\n"
|
||||
|
||||
"bind 0 \"impulse 0\"\n"
|
||||
|
||||
"bind / \"impulse 10\"\n"
|
||||
"bind MWHEELDOWN \"impulse 10\"\n"
|
||||
"bind MWHEELUP \"impulse 12\"\n"
|
||||
|
||||
"alias zoom_in \"sensitivity 2;fov 90;wait;fov 70;wait;fov 50;wait;fov 30;wait;fov 10;wait;fov 5;bind F11 zoom_out\"\n"
|
||||
"alias zoom_out \"sensitivity 4;fov 5;wait;fov 10;wait;fov 30;wait;fov 50;wait;fov 70;wait;fov 90;bind F11 zoom_in; sensitivity 3\"\n"
|
||||
"bind F11 zoom_in\n"
|
||||
|
||||
"bind F1 \"help\"\n"
|
||||
"bind F2 \"menu_save\"\n"
|
||||
"bind F3 \"menu_load\"\n"
|
||||
"bind F4 \"menu_options\"\n"
|
||||
"bind F5 \"menu_multiplayer\"\n"
|
||||
"bind F6 \"echo Quicksaving...; wait; save quick\"\n"
|
||||
"bind F9 \"echo Quickloading...; wait; load quick\"\n"
|
||||
"bind F10 \"quit\"\n"
|
||||
"bind F12 \"screenshot\"\n"
|
||||
|
||||
"bind \\ +mlook\n"
|
||||
|
||||
"bind PAUSE \"pause\"\n"
|
||||
"bind ESCAPE \"togglemenu\"\n"
|
||||
"bind ~ \"toggleconsole\"\n"
|
||||
"bind ` \"toggleconsole\"\n"
|
||||
|
||||
"bind t \"messagemode\"\n"
|
||||
|
||||
"bind + \"sizeup\"\n"
|
||||
"bind = \"sizeup\"\n"
|
||||
"bind - \"sizedown\"\n"
|
||||
|
||||
"bind INS +klook\n"
|
||||
|
||||
"bind MOUSE1 +attack\n"
|
||||
"bind MOUSE2 +jump\n"
|
||||
|
||||
"bind LSHOULDER \"impulse 12\"\n"
|
||||
"bind RSHOULDER \"impulse 10\"\n"
|
||||
"bind LTRIGGER +jump\n"
|
||||
"bind RTRIGGER +attack\n"
|
||||
|
||||
"gamma 1.0\n"
|
||||
"volume 0.7\n"
|
||||
"sensitivity 3\n"
|
||||
|
||||
"viewsize 110\n"
|
||||
"scr_conscale 1.6\n"
|
||||
"scr_menuscale 1.6\n"
|
||||
"scr_sbarscale 1.6\n"
|
||||
|
||||
"+mlook\n";
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 _QUAKE_DRAW_H
|
||||
#define _QUAKE_DRAW_H
|
||||
|
||||
// draw.h -- these are the only functions outside the refresh allowed
|
||||
// to touch the vid buffer
|
||||
|
||||
extern qpic_t *draw_disc; // also used on sbar
|
||||
|
||||
void Draw_Init (void);
|
||||
void Draw_Character (int x, int y, int num);
|
||||
void Draw_DebugChar (char num);
|
||||
void Draw_Pic (int x, int y, qpic_t *pic);
|
||||
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, int top, int bottom); //johnfitz -- more parameters
|
||||
void Draw_ConsoleBackground (void); //johnfitz -- removed parameter int lines
|
||||
void Draw_TileClear (int x, int y, int w, int h);
|
||||
void Draw_Fill (int x, int y, int w, int h, int c, float alpha); //johnfitz -- added alpha
|
||||
void Draw_FadeScreen (void);
|
||||
void Draw_String (int x, int y, const char *str);
|
||||
qpic_t *Draw_PicFromWad (const char *name);
|
||||
qpic_t *Draw_CachePic (const char *path);
|
||||
void Draw_NewGame (void);
|
||||
|
||||
void GL_SetCanvas (canvastype newcanvas); //johnfitz
|
||||
|
||||
#endif /* _QUAKE_DRAW_H */
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/* Macros for taking apart, interpreting and processing file names.
|
||||
*
|
||||
* These are here because some non-Posix (a.k.a. DOSish) systems have
|
||||
* drive letter brain-damage at the beginning of an absolute file name,
|
||||
* use forward- and back-slash in path names interchangeably, and
|
||||
* some of them have case-insensitive file names.
|
||||
*
|
||||
* This was based on filenames.h from BFD, the Binary File Descriptor
|
||||
* library, Copyright (C) 2000-2016 Free Software Foundation, Inc.,
|
||||
* and changed by O. Sezer <[email protected]> for our needs.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef FILENAMES_H
|
||||
#define FILENAMES_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* ---------------------- Windows, DOS, OS2: ---------------------- */
|
||||
#if defined(__MSDOS__) || defined(__DOS__) || defined(__DJGPP__) || \
|
||||
defined(_MSDOS) || defined(__OS2__) || defined(__EMX__) || \
|
||||
defined(_WIN32) || defined(_Windows) || defined(__WINDOWS__) || \
|
||||
defined(__NT__) || defined(__CYGWIN__)
|
||||
|
||||
#define HAVE_DOS_BASED_FILE_SYSTEM 1
|
||||
#define HAVE_CASE_INSENSITIVE_FILE_SYSTEM 1
|
||||
|
||||
#define HAS_DRIVE_SPEC(f) ((f)[0] && ((f)[1] == ':'))
|
||||
#define STRIP_DRIVE_SPEC(f) ((f) + 2)
|
||||
#define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\')
|
||||
/* both '/' and '\\' work as dir separator. djgpp likes changing
|
||||
* '\\' into '/', so I define DIR_SEPARATOR_CHAR as '/' for djgpp,
|
||||
* '\\' otherwise. */
|
||||
#ifdef __DJGPP__
|
||||
#define DIR_SEPARATOR_CHAR '/'
|
||||
#define DIR_SEPARATOR_STR "/"
|
||||
#else
|
||||
#define DIR_SEPARATOR_CHAR '\\'
|
||||
#define DIR_SEPARATOR_STR "\\"
|
||||
#endif
|
||||
/* Note that IS_ABSOLUTE_PATH accepts d:foo as well, although it is
|
||||
only semi-absolute. This is because the users of IS_ABSOLUTE_PATH
|
||||
want to know whether to prepend the current working directory to
|
||||
a file name, which should not be done with a name like d:foo. */
|
||||
#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || HAS_DRIVE_SPEC((f)))
|
||||
|
||||
#ifdef __cplusplus
|
||||
static inline char *FIND_FIRST_DIRSEP(char *_the_path) {
|
||||
/* FIXME: What about C:FOO ? */
|
||||
char *p1 = strchr(_the_path, '/');
|
||||
char *p2 = strchr(_the_path, '\\');
|
||||
if (p1 == NULL) return p2;
|
||||
if (p2 == NULL) return p1;
|
||||
return (p1 < p2)? p1 : p2;
|
||||
}
|
||||
static inline char *FIND_LAST_DIRSEP (char *_the_path) {
|
||||
/* FIXME: What about C:FOO ? */
|
||||
char *p1 = strrchr(_the_path, '/');
|
||||
char *p2 = strrchr(_the_path, '\\');
|
||||
if (p1 == NULL) return p2;
|
||||
if (p2 == NULL) return p1;
|
||||
return (p1 > p2)? p1 : p2;
|
||||
}
|
||||
static inline const char *FIND_FIRST_DIRSEP(const char *_the_path) {
|
||||
/* FIXME: What about C:FOO ? */
|
||||
const char *p1 = strchr(_the_path, '/');
|
||||
const char *p2 = strchr(_the_path, '\\');
|
||||
if (p1 == NULL) return p2;
|
||||
if (p2 == NULL) return p1;
|
||||
return (p1 < p2)? p1 : p2;
|
||||
}
|
||||
static inline const char *FIND_LAST_DIRSEP (const char *_the_path) {
|
||||
/* FIXME: What about C:FOO ? */
|
||||
const char *p1 = strrchr(_the_path, '/');
|
||||
const char *p2 = strrchr(_the_path, '\\');
|
||||
if (p1 == NULL) return p2;
|
||||
if (p2 == NULL) return p1;
|
||||
return (p1 > p2)? p1 : p2;
|
||||
}
|
||||
#else
|
||||
static inline char *FIND_FIRST_DIRSEP(const char *_the_path) {
|
||||
/* FIXME: What about C:FOO ? */
|
||||
char *p1 = strchr(_the_path, '/');
|
||||
char *p2 = strchr(_the_path, '\\');
|
||||
if (p1 == NULL) return p2;
|
||||
if (p2 == NULL) return p1;
|
||||
return (p1 < p2)? p1 : p2;
|
||||
}
|
||||
static inline char *FIND_LAST_DIRSEP (const char *_the_path) {
|
||||
/* FIXME: What about C:FOO ? */
|
||||
char *p1 = strrchr(_the_path, '/');
|
||||
char *p2 = strrchr(_the_path, '\\');
|
||||
if (p1 == NULL) return p2;
|
||||
if (p2 == NULL) return p1;
|
||||
return (p1 > p2)? p1 : p2;
|
||||
}
|
||||
#endif /* C++ */
|
||||
|
||||
/* ----------------- AmigaOS, MorphOS, AROS, etc: ----------------- */
|
||||
#elif defined(__MORPHOS__) || defined(__AROS__) || defined(AMIGAOS) || \
|
||||
defined(__amigaos__) || defined(__amigaos4__) ||defined(__amigados__) || \
|
||||
defined(AMIGA) || defined(_AMIGA) || defined(__AMIGA__)
|
||||
|
||||
#define HAS_DRIVE_SPEC(f) (0) /* */
|
||||
#define STRIP_DRIVE_SPEC(f) (f) /* */
|
||||
#define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == ':')
|
||||
#define DIR_SEPARATOR_CHAR '/'
|
||||
#define DIR_SEPARATOR_STR "/"
|
||||
#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]) || (strchr((f), ':')))
|
||||
#define HAVE_CASE_INSENSITIVE_FILE_SYSTEM 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
static inline char *FIND_FIRST_DIRSEP(char *_the_path) {
|
||||
char *p = strchr(_the_path, ':');
|
||||
if (p != NULL) return p;
|
||||
return strchr(_the_path, '/');
|
||||
}
|
||||
static inline char *FIND_LAST_DIRSEP (char *_the_path) {
|
||||
char *p = strrchr(_the_path, '/');
|
||||
if (p != NULL) return p;
|
||||
return strchr(_the_path, ':');
|
||||
}
|
||||
static inline const char *FIND_FIRST_DIRSEP(const char *_the_path) {
|
||||
const char *p = strchr(_the_path, ':');
|
||||
if (p != NULL) return p;
|
||||
return strchr(_the_path, '/');
|
||||
}
|
||||
static inline const char *FIND_LAST_DIRSEP (const char *_the_path) {
|
||||
const char *p = strrchr(_the_path, '/');
|
||||
if (p != NULL) return p;
|
||||
return strchr(_the_path, ':');
|
||||
}
|
||||
#else
|
||||
static inline char *FIND_FIRST_DIRSEP(const char *_the_path) {
|
||||
char *p = strchr(_the_path, ':');
|
||||
if (p != NULL) return p;
|
||||
return strchr(_the_path, '/');
|
||||
}
|
||||
static inline char *FIND_LAST_DIRSEP (const char *_the_path) {
|
||||
char *p = strrchr(_the_path, '/');
|
||||
if (p != NULL) return p;
|
||||
return strchr(_the_path, ':');
|
||||
}
|
||||
#endif /* C++ */
|
||||
|
||||
/* ---------------------- assumed UNIX-ish : ---------------------- */
|
||||
#else /* */
|
||||
|
||||
#define IS_DIR_SEPARATOR(c) ((c) == '/')
|
||||
#define DIR_SEPARATOR_CHAR '/'
|
||||
#define DIR_SEPARATOR_STR "/"
|
||||
#define IS_ABSOLUTE_PATH(f) (IS_DIR_SEPARATOR((f)[0]))
|
||||
#define HAS_DRIVE_SPEC(f) (0)
|
||||
#define STRIP_DRIVE_SPEC(f) (f)
|
||||
|
||||
#ifdef __cplusplus
|
||||
static inline char *FIND_FIRST_DIRSEP(char *_the_path) {
|
||||
return strchr(_the_path, '/');
|
||||
}
|
||||
static inline char *FIND_LAST_DIRSEP (char *_the_path) {
|
||||
return strrchr(_the_path, '/');
|
||||
}
|
||||
static inline const char *FIND_FIRST_DIRSEP(const char *_the_path) {
|
||||
return strchr(_the_path, '/');
|
||||
}
|
||||
static inline const char *FIND_LAST_DIRSEP (const char *_the_path) {
|
||||
return strrchr(_the_path, '/');
|
||||
}
|
||||
#else
|
||||
static inline char *FIND_FIRST_DIRSEP(const char *_the_path) {
|
||||
return strchr(_the_path, '/');
|
||||
}
|
||||
static inline char *FIND_LAST_DIRSEP (const char *_the_path) {
|
||||
return strrchr(_the_path, '/');
|
||||
}
|
||||
#endif /* C++ */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* FILENAMES_H */
|
||||
@@ -0,0 +1,772 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2007-2008 Kristian Duske
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
// draw.c -- 2d drawing
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
//extern unsigned char d_15to8table[65536]; //johnfitz -- never used
|
||||
|
||||
cvar_t scr_conalpha = {"scr_conalpha", "0.5", CVAR_ARCHIVE}; //johnfitz
|
||||
|
||||
qpic_t *draw_disc;
|
||||
qpic_t *draw_backtile;
|
||||
|
||||
gltexture_t *char_texture; //johnfitz
|
||||
qpic_t *pic_ovr, *pic_ins; //johnfitz -- new cursor handling
|
||||
qpic_t *pic_nul; //johnfitz -- for missing gfx, don't crash
|
||||
|
||||
//johnfitz -- new pics
|
||||
byte pic_ovr_data[8][8] =
|
||||
{
|
||||
{255,255,255,255,255,255,255,255},
|
||||
{255, 15, 15, 15, 15, 15, 15,255},
|
||||
{255, 15, 15, 15, 15, 15, 15, 2},
|
||||
{255, 15, 15, 15, 15, 15, 15, 2},
|
||||
{255, 15, 15, 15, 15, 15, 15, 2},
|
||||
{255, 15, 15, 15, 15, 15, 15, 2},
|
||||
{255, 15, 15, 15, 15, 15, 15, 2},
|
||||
{255,255, 2, 2, 2, 2, 2, 2},
|
||||
};
|
||||
|
||||
byte pic_ins_data[9][8] =
|
||||
{
|
||||
{ 15, 15,255,255,255,255,255,255},
|
||||
{ 15, 15, 2,255,255,255,255,255},
|
||||
{ 15, 15, 2,255,255,255,255,255},
|
||||
{ 15, 15, 2,255,255,255,255,255},
|
||||
{ 15, 15, 2,255,255,255,255,255},
|
||||
{ 15, 15, 2,255,255,255,255,255},
|
||||
{ 15, 15, 2,255,255,255,255,255},
|
||||
{ 15, 15, 2,255,255,255,255,255},
|
||||
{255, 2, 2,255,255,255,255,255},
|
||||
};
|
||||
|
||||
byte pic_nul_data[8][8] =
|
||||
{
|
||||
{252,252,252,252, 0, 0, 0, 0},
|
||||
{252,252,252,252, 0, 0, 0, 0},
|
||||
{252,252,252,252, 0, 0, 0, 0},
|
||||
{252,252,252,252, 0, 0, 0, 0},
|
||||
{ 0, 0, 0, 0,252,252,252,252},
|
||||
{ 0, 0, 0, 0,252,252,252,252},
|
||||
{ 0, 0, 0, 0,252,252,252,252},
|
||||
{ 0, 0, 0, 0,252,252,252,252},
|
||||
};
|
||||
|
||||
byte pic_stipple_data[8][8] =
|
||||
{
|
||||
{255, 0, 0, 0,255, 0, 0, 0},
|
||||
{ 0, 0,255, 0, 0, 0,255, 0},
|
||||
{255, 0, 0, 0,255, 0, 0, 0},
|
||||
{ 0, 0,255, 0, 0, 0,255, 0},
|
||||
{255, 0, 0, 0,255, 0, 0, 0},
|
||||
{ 0, 0,255, 0, 0, 0,255, 0},
|
||||
{255, 0, 0, 0,255, 0, 0, 0},
|
||||
{ 0, 0,255, 0, 0, 0,255, 0},
|
||||
};
|
||||
|
||||
byte pic_crosshair_data[8][8] =
|
||||
{
|
||||
{255,255,255,255,255,255,255,255},
|
||||
{255,255,255, 8, 9,255,255,255},
|
||||
{255,255,255, 6, 8, 2,255,255},
|
||||
{255, 6, 8, 8, 6, 8, 8,255},
|
||||
{255,255, 2, 8, 8, 2, 2, 2},
|
||||
{255,255,255, 7, 8, 2,255,255},
|
||||
{255,255,255,255, 2, 2,255,255},
|
||||
{255,255,255,255,255,255,255,255},
|
||||
};
|
||||
//johnfitz
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gltexture_t *gltexture;
|
||||
float sl, tl, sh, th;
|
||||
} glpic_t;
|
||||
|
||||
canvastype currentcanvas = CANVAS_NONE; //johnfitz -- for GL_SetCanvas
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// PIC CACHING
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
typedef struct cachepic_s
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
qpic_t pic;
|
||||
byte padding[32]; // for appended glpic
|
||||
} cachepic_t;
|
||||
|
||||
#define MAX_CACHED_PICS 128
|
||||
cachepic_t menu_cachepics[MAX_CACHED_PICS];
|
||||
int menu_numcachepics;
|
||||
|
||||
byte menuplyr_pixels[4096];
|
||||
|
||||
// scrap allocation
|
||||
// Allocate all the little status bar obejcts into a single texture
|
||||
// to crutch up stupid hardware / drivers
|
||||
|
||||
#define MAX_SCRAPS 2
|
||||
#define BLOCK_WIDTH 256
|
||||
#define BLOCK_HEIGHT 256
|
||||
|
||||
int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
|
||||
byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT]; //johnfitz -- removed *4 after BLOCK_HEIGHT
|
||||
qboolean scrap_dirty;
|
||||
gltexture_t *scrap_textures[MAX_SCRAPS]; //johnfitz
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Scrap_AllocBlock
|
||||
|
||||
returns an index into scrap_texnums[] and the position inside it
|
||||
================
|
||||
*/
|
||||
int Scrap_AllocBlock (int w, int h, int *x, int *y)
|
||||
{
|
||||
int i, j;
|
||||
int best, best2;
|
||||
int texnum;
|
||||
|
||||
for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
|
||||
{
|
||||
best = BLOCK_HEIGHT;
|
||||
|
||||
for (i=0 ; i<BLOCK_WIDTH-w ; i++)
|
||||
{
|
||||
best2 = 0;
|
||||
|
||||
for (j=0 ; j<w ; j++)
|
||||
{
|
||||
if (scrap_allocated[texnum][i+j] >= best)
|
||||
break;
|
||||
if (scrap_allocated[texnum][i+j] > best2)
|
||||
best2 = scrap_allocated[texnum][i+j];
|
||||
}
|
||||
if (j == w)
|
||||
{ // this is a valid spot
|
||||
*x = i;
|
||||
*y = best = best2;
|
||||
}
|
||||
}
|
||||
|
||||
if (best + h > BLOCK_HEIGHT)
|
||||
continue;
|
||||
|
||||
for (i=0 ; i<w ; i++)
|
||||
scrap_allocated[texnum][*x + i] = best + h;
|
||||
|
||||
return texnum;
|
||||
}
|
||||
|
||||
Sys_Error ("Scrap_AllocBlock: full"); //johnfitz -- correct function name
|
||||
return 0; //johnfitz -- shut up compiler
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Scrap_Upload -- johnfitz -- now uses TexMgr
|
||||
================
|
||||
*/
|
||||
void Scrap_Upload (void)
|
||||
{
|
||||
char name[8];
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAX_SCRAPS; i++)
|
||||
{
|
||||
sprintf (name, "scrap%i", i);
|
||||
scrap_textures[i] = TexMgr_LoadImage (NULL, name, BLOCK_WIDTH, BLOCK_HEIGHT, SRC_INDEXED, scrap_texels[i],
|
||||
"", (src_offset_t)scrap_texels[i], TEXPREF_ALPHA | TEXPREF_OVERWRITE | TEXPREF_NOPICMIP);
|
||||
}
|
||||
|
||||
scrap_dirty = false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_PicFromWad
|
||||
================
|
||||
*/
|
||||
qpic_t *Draw_PicFromWad (const char *name)
|
||||
{
|
||||
qpic_t *p;
|
||||
glpic_t gl;
|
||||
src_offset_t offset; //johnfitz
|
||||
|
||||
p = (qpic_t *) W_GetLumpName (name);
|
||||
if (!p) return pic_nul; //johnfitz
|
||||
|
||||
// load little ones into the scrap
|
||||
if (p->width < 64 && p->height < 64)
|
||||
{
|
||||
int x, y;
|
||||
int i, j, k;
|
||||
int texnum;
|
||||
|
||||
texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
|
||||
scrap_dirty = true;
|
||||
k = 0;
|
||||
for (i=0 ; i<p->height ; i++)
|
||||
{
|
||||
for (j=0 ; j<p->width ; j++, k++)
|
||||
scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
|
||||
}
|
||||
gl.gltexture = scrap_textures[texnum]; //johnfitz -- changed to an array
|
||||
//johnfitz -- no longer go from 0.01 to 0.99
|
||||
gl.sl = x/(float)BLOCK_WIDTH;
|
||||
gl.sh = (x+p->width)/(float)BLOCK_WIDTH;
|
||||
gl.tl = y/(float)BLOCK_WIDTH;
|
||||
gl.th = (y+p->height)/(float)BLOCK_WIDTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
char texturename[64]; //johnfitz
|
||||
q_snprintf (texturename, sizeof(texturename), "%s:%s", WADFILENAME, name); //johnfitz
|
||||
|
||||
offset = (src_offset_t)p - (src_offset_t)wad_base + sizeof(int)*2; //johnfitz
|
||||
|
||||
gl.gltexture = TexMgr_LoadImage (NULL, texturename, p->width, p->height, SRC_INDEXED, p->data, WADFILENAME,
|
||||
offset, TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP); //johnfitz -- TexMgr
|
||||
gl.sl = 0;
|
||||
gl.sh = (float)p->width/(float)TexMgr_PadConditional(p->width); //johnfitz
|
||||
gl.tl = 0;
|
||||
gl.th = (float)p->height/(float)TexMgr_PadConditional(p->height); //johnfitz
|
||||
}
|
||||
|
||||
memcpy (p->data, &gl, sizeof(glpic_t));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_CachePic
|
||||
================
|
||||
*/
|
||||
qpic_t *Draw_CachePic (const char *path)
|
||||
{
|
||||
cachepic_t *pic;
|
||||
int i;
|
||||
qpic_t *dat;
|
||||
glpic_t gl;
|
||||
|
||||
for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
|
||||
{
|
||||
if (!strcmp (path, pic->name))
|
||||
return &pic->pic;
|
||||
}
|
||||
if (menu_numcachepics == MAX_CACHED_PICS)
|
||||
Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
|
||||
menu_numcachepics++;
|
||||
strcpy (pic->name, path);
|
||||
|
||||
//
|
||||
// load the pic from disk
|
||||
//
|
||||
dat = (qpic_t *)COM_LoadTempFile (path, NULL);
|
||||
if (!dat)
|
||||
Sys_Error ("Draw_CachePic: failed to load %s", path);
|
||||
SwapPic (dat);
|
||||
|
||||
// HACK HACK HACK --- we need to keep the bytes for
|
||||
// the translatable player picture just for the menu
|
||||
// configuration dialog
|
||||
if (!strcmp (path, "gfx/menuplyr.lmp"))
|
||||
memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
|
||||
|
||||
pic->pic.width = dat->width;
|
||||
pic->pic.height = dat->height;
|
||||
|
||||
gl.gltexture = TexMgr_LoadImage (NULL, path, dat->width, dat->height, SRC_INDEXED, dat->data, path,
|
||||
sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP); //johnfitz -- TexMgr
|
||||
gl.sl = 0;
|
||||
gl.sh = (float)dat->width/(float)TexMgr_PadConditional(dat->width); //johnfitz
|
||||
gl.tl = 0;
|
||||
gl.th = (float)dat->height/(float)TexMgr_PadConditional(dat->height); //johnfitz
|
||||
memcpy (pic->pic.data, &gl, sizeof(glpic_t));
|
||||
|
||||
return &pic->pic;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_MakePic -- johnfitz -- generate pics from internal data
|
||||
================
|
||||
*/
|
||||
qpic_t *Draw_MakePic (const char *name, int width, int height, byte *data)
|
||||
{
|
||||
int flags = TEXPREF_NEAREST | TEXPREF_ALPHA | TEXPREF_PERSIST | TEXPREF_NOPICMIP | TEXPREF_PAD;
|
||||
qpic_t *pic;
|
||||
glpic_t gl;
|
||||
|
||||
pic = (qpic_t *) Hunk_Alloc (sizeof(qpic_t) - 4 + sizeof (glpic_t));
|
||||
pic->width = width;
|
||||
pic->height = height;
|
||||
|
||||
gl.gltexture = TexMgr_LoadImage (NULL, name, width, height, SRC_INDEXED, data, "", (src_offset_t)data, flags);
|
||||
gl.sl = 0;
|
||||
gl.sh = (float)width/(float)TexMgr_PadConditional(width);
|
||||
gl.tl = 0;
|
||||
gl.th = (float)height/(float)TexMgr_PadConditional(height);
|
||||
memcpy (pic->data, &gl, sizeof(glpic_t));
|
||||
|
||||
return pic;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// INIT
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
===============
|
||||
Draw_LoadPics -- johnfitz
|
||||
===============
|
||||
*/
|
||||
void Draw_LoadPics (void)
|
||||
{
|
||||
byte *data;
|
||||
src_offset_t offset;
|
||||
|
||||
data = (byte *) W_GetLumpName ("conchars");
|
||||
if (!data) Sys_Error ("Draw_LoadPics: couldn't load conchars");
|
||||
offset = (src_offset_t)data - (src_offset_t)wad_base;
|
||||
char_texture = TexMgr_LoadImage (NULL, WADFILENAME":conchars", 128, 128, SRC_INDEXED, data,
|
||||
WADFILENAME, offset, TEXPREF_ALPHA | TEXPREF_NEAREST | TEXPREF_NOPICMIP | TEXPREF_CONCHARS);
|
||||
|
||||
draw_disc = Draw_PicFromWad ("disc");
|
||||
draw_backtile = Draw_PicFromWad ("backtile");
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Draw_NewGame -- johnfitz
|
||||
===============
|
||||
*/
|
||||
void Draw_NewGame (void)
|
||||
{
|
||||
cachepic_t *pic;
|
||||
int i;
|
||||
|
||||
// empty scrap and reallocate gltextures
|
||||
memset(scrap_allocated, 0, sizeof(scrap_allocated));
|
||||
memset(scrap_texels, 255, sizeof(scrap_texels));
|
||||
|
||||
Scrap_Upload (); //creates 2 empty gltextures
|
||||
|
||||
// reload wad pics
|
||||
W_LoadWadFile (); //johnfitz -- filename is now hard-coded for honesty
|
||||
Draw_LoadPics ();
|
||||
SCR_LoadPics ();
|
||||
Sbar_LoadPics ();
|
||||
|
||||
// empty lmp cache
|
||||
for (pic = menu_cachepics, i = 0; i < menu_numcachepics; pic++, i++)
|
||||
pic->name[0] = 0;
|
||||
menu_numcachepics = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Draw_Init -- johnfitz -- rewritten
|
||||
===============
|
||||
*/
|
||||
void Draw_Init (void)
|
||||
{
|
||||
Cvar_RegisterVariable (&scr_conalpha);
|
||||
|
||||
// clear scrap and allocate gltextures
|
||||
memset(scrap_allocated, 0, sizeof(scrap_allocated));
|
||||
memset(scrap_texels, 255, sizeof(scrap_texels));
|
||||
|
||||
Scrap_Upload (); //creates 2 empty textures
|
||||
|
||||
// create internal pics
|
||||
pic_ins = Draw_MakePic ("ins", 8, 9, &pic_ins_data[0][0]);
|
||||
pic_ovr = Draw_MakePic ("ovr", 8, 8, &pic_ovr_data[0][0]);
|
||||
pic_nul = Draw_MakePic ("nul", 8, 8, &pic_nul_data[0][0]);
|
||||
|
||||
// load game pics
|
||||
Draw_LoadPics ();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// 2D DRAWING
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_CharacterQuad -- johnfitz -- seperate function to spit out verts
|
||||
================
|
||||
*/
|
||||
void Draw_CharacterQuad (int x, int y, char num)
|
||||
{
|
||||
int row, col;
|
||||
float frow, fcol, size;
|
||||
|
||||
row = num>>4;
|
||||
col = num&15;
|
||||
|
||||
frow = row*0.0625;
|
||||
fcol = col*0.0625;
|
||||
size = 0.0625;
|
||||
|
||||
glTexCoord2f (fcol, frow);
|
||||
glVertex2f (x, y);
|
||||
glTexCoord2f (fcol + size, frow);
|
||||
glVertex2f (x+8, y);
|
||||
glTexCoord2f (fcol + size, frow + size);
|
||||
glVertex2f (x+8, y+8);
|
||||
glTexCoord2f (fcol, frow + size);
|
||||
glVertex2f (x, y+8);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_Character -- johnfitz -- modified to call Draw_CharacterQuad
|
||||
================
|
||||
*/
|
||||
void Draw_Character (int x, int y, int num)
|
||||
{
|
||||
if (y <= -8)
|
||||
return; // totally off screen
|
||||
|
||||
num &= 255;
|
||||
|
||||
if (num == 32)
|
||||
return; //don't waste verts on spaces
|
||||
|
||||
GL_Bind (char_texture);
|
||||
glBegin (GL_QUADS);
|
||||
|
||||
Draw_CharacterQuad (x, y, (char) num);
|
||||
|
||||
glEnd ();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_String -- johnfitz -- modified to call Draw_CharacterQuad
|
||||
================
|
||||
*/
|
||||
void Draw_String (int x, int y, const char *str)
|
||||
{
|
||||
if (y <= -8)
|
||||
return; // totally off screen
|
||||
|
||||
GL_Bind (char_texture);
|
||||
glBegin (GL_QUADS);
|
||||
|
||||
while (*str)
|
||||
{
|
||||
if (*str != 32) //don't waste verts on spaces
|
||||
Draw_CharacterQuad (x, y, *str);
|
||||
str++;
|
||||
x += 8;
|
||||
}
|
||||
|
||||
glEnd ();
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_Pic -- johnfitz -- modified
|
||||
=============
|
||||
*/
|
||||
void Draw_Pic (int x, int y, qpic_t *pic)
|
||||
{
|
||||
glpic_t *gl;
|
||||
|
||||
if (scrap_dirty)
|
||||
Scrap_Upload ();
|
||||
gl = (glpic_t *)pic->data;
|
||||
GL_Bind (gl->gltexture);
|
||||
glBegin (GL_QUADS);
|
||||
glTexCoord2f (gl->sl, gl->tl);
|
||||
glVertex2f (x, y);
|
||||
glTexCoord2f (gl->sh, gl->tl);
|
||||
glVertex2f (x+pic->width, y);
|
||||
glTexCoord2f (gl->sh, gl->th);
|
||||
glVertex2f (x+pic->width, y+pic->height);
|
||||
glTexCoord2f (gl->sl, gl->th);
|
||||
glVertex2f (x, y+pic->height);
|
||||
glEnd ();
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_TransPicTranslate -- johnfitz -- rewritten to use texmgr to do translation
|
||||
|
||||
Only used for the player color selection menu
|
||||
=============
|
||||
*/
|
||||
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, int top, int bottom)
|
||||
{
|
||||
static int oldtop = -2;
|
||||
static int oldbottom = -2;
|
||||
|
||||
if (top != oldtop || bottom != oldbottom)
|
||||
{
|
||||
glpic_t *p = (glpic_t *)pic->data;
|
||||
gltexture_t *glt = p->gltexture;
|
||||
oldtop = top;
|
||||
oldbottom = bottom;
|
||||
TexMgr_ReloadImage (glt, top, bottom);
|
||||
}
|
||||
Draw_Pic (x, y, pic);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_ConsoleBackground -- johnfitz -- rewritten
|
||||
================
|
||||
*/
|
||||
void Draw_ConsoleBackground (void)
|
||||
{
|
||||
qpic_t *pic;
|
||||
float alpha;
|
||||
|
||||
pic = Draw_CachePic ("gfx/conback.lmp");
|
||||
pic->width = vid.conwidth;
|
||||
pic->height = vid.conheight;
|
||||
|
||||
alpha = (con_forcedup) ? 1.0f : scr_conalpha.value;
|
||||
|
||||
GL_SetCanvas (CANVAS_CONSOLE); //in case this is called from weird places
|
||||
|
||||
if (alpha > 0.0f)
|
||||
{
|
||||
if (alpha < 1.0f)
|
||||
{
|
||||
glEnable (GL_BLEND);
|
||||
glColor4f (1,1,1,alpha);
|
||||
glDisable (GL_ALPHA_TEST);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
}
|
||||
|
||||
Draw_Pic (0, 0, pic);
|
||||
|
||||
if (alpha < 1.0f)
|
||||
{
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||
glEnable (GL_ALPHA_TEST);
|
||||
glDisable (GL_BLEND);
|
||||
glColor4f (1,1,1,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_TileClear
|
||||
|
||||
This repeats a 64*64 tile graphic to fill the screen around a sized down
|
||||
refresh window.
|
||||
=============
|
||||
*/
|
||||
void Draw_TileClear (int x, int y, int w, int h)
|
||||
{
|
||||
glpic_t *gl;
|
||||
|
||||
gl = (glpic_t *)draw_backtile->data;
|
||||
|
||||
glColor3f (1,1,1);
|
||||
GL_Bind (gl->gltexture);
|
||||
glBegin (GL_QUADS);
|
||||
glTexCoord2f (x/64.0, y/64.0);
|
||||
glVertex2f (x, y);
|
||||
glTexCoord2f ( (x+w)/64.0, y/64.0);
|
||||
glVertex2f (x+w, y);
|
||||
glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
|
||||
glVertex2f (x+w, y+h);
|
||||
glTexCoord2f ( x/64.0, (y+h)/64.0 );
|
||||
glVertex2f (x, y+h);
|
||||
glEnd ();
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_Fill
|
||||
|
||||
Fills a box of pixels with a single color
|
||||
=============
|
||||
*/
|
||||
void Draw_Fill (int x, int y, int w, int h, int c, float alpha) //johnfitz -- added alpha
|
||||
{
|
||||
byte *pal = (byte *)d_8to24table; //johnfitz -- use d_8to24table instead of host_basepal
|
||||
|
||||
glDisable (GL_TEXTURE_2D);
|
||||
glEnable (GL_BLEND); //johnfitz -- for alpha
|
||||
glDisable (GL_ALPHA_TEST); //johnfitz -- for alpha
|
||||
glColor4f (pal[c*4]/255.0, pal[c*4+1]/255.0, pal[c*4+2]/255.0, alpha); //johnfitz -- added alpha
|
||||
|
||||
glBegin (GL_QUADS);
|
||||
glVertex2f (x,y);
|
||||
glVertex2f (x+w, y);
|
||||
glVertex2f (x+w, y+h);
|
||||
glVertex2f (x, y+h);
|
||||
glEnd ();
|
||||
|
||||
glColor3f (1,1,1);
|
||||
glDisable (GL_BLEND); //johnfitz -- for alpha
|
||||
glEnable (GL_ALPHA_TEST); //johnfitz -- for alpha
|
||||
glEnable (GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Draw_FadeScreen -- johnfitz -- revised
|
||||
================
|
||||
*/
|
||||
void Draw_FadeScreen (void)
|
||||
{
|
||||
GL_SetCanvas (CANVAS_DEFAULT);
|
||||
|
||||
glEnable (GL_BLEND);
|
||||
glDisable (GL_ALPHA_TEST);
|
||||
glDisable (GL_TEXTURE_2D);
|
||||
glColor4f (0, 0, 0, 0.5);
|
||||
glBegin (GL_QUADS);
|
||||
|
||||
glVertex2f (0,0);
|
||||
glVertex2f (glwidth, 0);
|
||||
glVertex2f (glwidth, glheight);
|
||||
glVertex2f (0, glheight);
|
||||
|
||||
glEnd ();
|
||||
glColor4f (1,1,1,1);
|
||||
glEnable (GL_TEXTURE_2D);
|
||||
glEnable (GL_ALPHA_TEST);
|
||||
glDisable (GL_BLEND);
|
||||
|
||||
Sbar_Changed();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GL_SetCanvas -- johnfitz -- support various canvas types
|
||||
================
|
||||
*/
|
||||
void GL_SetCanvas (canvastype newcanvas)
|
||||
{
|
||||
extern vrect_t scr_vrect;
|
||||
float s;
|
||||
int lines;
|
||||
|
||||
if (newcanvas == currentcanvas)
|
||||
return;
|
||||
|
||||
currentcanvas = newcanvas;
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity ();
|
||||
|
||||
switch(newcanvas)
|
||||
{
|
||||
case CANVAS_DEFAULT:
|
||||
glOrtho (0, glwidth, glheight, 0, -99999, 99999);
|
||||
glViewport (glx, gly, glwidth, glheight);
|
||||
break;
|
||||
case CANVAS_CONSOLE:
|
||||
lines = vid.conheight - (scr_con_current * vid.conheight / glheight);
|
||||
glOrtho (0, vid.conwidth, vid.conheight + lines, lines, -99999, 99999);
|
||||
glViewport (glx, gly, glwidth, glheight);
|
||||
break;
|
||||
case CANVAS_MENU:
|
||||
s = q_min((float)glwidth / 320.0f, (float)glheight / 200.0f);
|
||||
s = CLAMP (1.0f, scr_menuscale.value, s);
|
||||
// ericw -- doubled width to 640 to accommodate long keybindings
|
||||
glOrtho (0, 640, 200, 0, -99999, 99999);
|
||||
glViewport (glx + (glwidth - 320*s) / 2, gly + (glheight - 200*s) / 2, 640*s, 200*s);
|
||||
break;
|
||||
case CANVAS_SBAR:
|
||||
s = CLAMP (1.0f, scr_sbarscale.value, (float)glwidth / 320.0f);
|
||||
if (cl.gametype == GAME_DEATHMATCH)
|
||||
{
|
||||
glOrtho (0, glwidth / s, 48, 0, -99999, 99999);
|
||||
glViewport (glx, gly, glwidth, 48*s);
|
||||
}
|
||||
else
|
||||
{
|
||||
glOrtho (0, 320, 48, 0, -99999, 99999);
|
||||
glViewport (glx + (glwidth - 320*s) / 2, gly, 320*s, 48*s);
|
||||
}
|
||||
break;
|
||||
case CANVAS_WARPIMAGE:
|
||||
glOrtho (0, 128, 0, 128, -99999, 99999);
|
||||
glViewport (glx, gly+glheight-gl_warpimagesize, gl_warpimagesize, gl_warpimagesize);
|
||||
break;
|
||||
case CANVAS_CROSSHAIR: //0,0 is center of viewport
|
||||
s = CLAMP (1.0f, scr_crosshairscale.value, 10.0f);
|
||||
glOrtho (scr_vrect.width/-2/s, scr_vrect.width/2/s, scr_vrect.height/2/s, scr_vrect.height/-2/s, -99999, 99999);
|
||||
glViewport (scr_vrect.x, glheight - scr_vrect.y - scr_vrect.height, scr_vrect.width & ~1, scr_vrect.height & ~1);
|
||||
break;
|
||||
case CANVAS_BOTTOMLEFT: //used by devstats
|
||||
s = (float)glwidth/vid.conwidth; //use console scale
|
||||
glOrtho (0, 320, 200, 0, -99999, 99999);
|
||||
glViewport (glx, gly, 320*s, 200*s);
|
||||
break;
|
||||
case CANVAS_BOTTOMRIGHT: //used by fps/clock
|
||||
s = (float)glwidth/vid.conwidth; //use console scale
|
||||
glOrtho (0, 320, 200, 0, -99999, 99999);
|
||||
glViewport (glx+glwidth-320*s, gly, 320*s, 200*s);
|
||||
break;
|
||||
case CANVAS_TOPRIGHT: //used by disc
|
||||
s = 1;
|
||||
glOrtho (0, 320, 200, 0, -99999, 99999);
|
||||
glViewport (glx+glwidth-320*s, gly+glheight-200*s, 320*s, 200*s);
|
||||
break;
|
||||
default:
|
||||
Sys_Error ("GL_SetCanvas: bad canvas type");
|
||||
}
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity ();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GL_Set2D -- johnfitz -- rewritten
|
||||
================
|
||||
*/
|
||||
void GL_Set2D (void)
|
||||
{
|
||||
currentcanvas = CANVAS_INVALID;
|
||||
GL_SetCanvas (CANVAS_DEFAULT);
|
||||
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glDisable (GL_CULL_FACE);
|
||||
glDisable (GL_BLEND);
|
||||
glEnable (GL_ALPHA_TEST);
|
||||
glColor4f (1,1,1,1);
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2007-2008 Kristian Duske
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
*/
|
||||
//gl_fog.c -- global and volumetric fog
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// GLOBAL FOG
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
#define DEFAULT_DENSITY 0.0
|
||||
#define DEFAULT_GRAY 0.3
|
||||
|
||||
static float fog_density;
|
||||
static float fog_red;
|
||||
static float fog_green;
|
||||
static float fog_blue;
|
||||
|
||||
static float old_density;
|
||||
static float old_red;
|
||||
static float old_green;
|
||||
static float old_blue;
|
||||
|
||||
static float fade_time; //duration of fade
|
||||
static float fade_done; //time when fade will be done
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_Update
|
||||
|
||||
update internal variables
|
||||
=============
|
||||
*/
|
||||
void Fog_Update (float density, float red, float green, float blue, float time)
|
||||
{
|
||||
//save previous settings for fade
|
||||
if (time > 0)
|
||||
{
|
||||
//check for a fade in progress
|
||||
if (fade_done > cl.time)
|
||||
{
|
||||
float f;
|
||||
|
||||
f = (fade_done - cl.time) / fade_time;
|
||||
old_density = f * old_density + (1.0 - f) * fog_density;
|
||||
old_red = f * old_red + (1.0 - f) * fog_red;
|
||||
old_green = f * old_green + (1.0 - f) * fog_green;
|
||||
old_blue = f * old_blue + (1.0 - f) * fog_blue;
|
||||
}
|
||||
else
|
||||
{
|
||||
old_density = fog_density;
|
||||
old_red = fog_red;
|
||||
old_green = fog_green;
|
||||
old_blue = fog_blue;
|
||||
}
|
||||
}
|
||||
|
||||
fog_density = density;
|
||||
fog_red = red;
|
||||
fog_green = green;
|
||||
fog_blue = blue;
|
||||
fade_time = time;
|
||||
fade_done = cl.time + time;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_ParseServerMessage
|
||||
|
||||
handle an SVC_FOG message from server
|
||||
=============
|
||||
*/
|
||||
void Fog_ParseServerMessage (void)
|
||||
{
|
||||
float density, red, green, blue, time;
|
||||
|
||||
density = MSG_ReadByte() / 255.0;
|
||||
red = MSG_ReadByte() / 255.0;
|
||||
green = MSG_ReadByte() / 255.0;
|
||||
blue = MSG_ReadByte() / 255.0;
|
||||
time = MSG_ReadShort() / 100.0;
|
||||
if (time < 0.0f) time = 0.0f;
|
||||
|
||||
Fog_Update (density, red, green, blue, time);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_FogCommand_f
|
||||
|
||||
handle the 'fog' console command
|
||||
=============
|
||||
*/
|
||||
void Fog_FogCommand_f (void)
|
||||
{
|
||||
float d, r, g, b, t;
|
||||
|
||||
switch (Cmd_Argc())
|
||||
{
|
||||
default:
|
||||
case 1:
|
||||
Con_Printf("usage:\n");
|
||||
Con_Printf(" fog <density>\n");
|
||||
Con_Printf(" fog <red> <green> <blue>\n");
|
||||
Con_Printf(" fog <density> <red> <green> <blue>\n");
|
||||
Con_Printf("current values:\n");
|
||||
Con_Printf(" \"density\" is \"%f\"\n", fog_density);
|
||||
Con_Printf(" \"red\" is \"%f\"\n", fog_red);
|
||||
Con_Printf(" \"green\" is \"%f\"\n", fog_green);
|
||||
Con_Printf(" \"blue\" is \"%f\"\n", fog_blue);
|
||||
return;
|
||||
case 2:
|
||||
d = Q_atof(Cmd_Argv(1));
|
||||
t = 0.0f;
|
||||
r = fog_red;
|
||||
g = fog_green;
|
||||
b = fog_blue;
|
||||
break;
|
||||
case 3: //TEST
|
||||
d = Q_atof(Cmd_Argv(1));
|
||||
t = Q_atof(Cmd_Argv(2));
|
||||
r = fog_red;
|
||||
g = fog_green;
|
||||
b = fog_blue;
|
||||
break;
|
||||
case 4:
|
||||
d = fog_density;
|
||||
t = 0.0f;
|
||||
r = Q_atof(Cmd_Argv(1));
|
||||
g = Q_atof(Cmd_Argv(2));
|
||||
b = Q_atof(Cmd_Argv(3));
|
||||
break;
|
||||
case 5:
|
||||
d = Q_atof(Cmd_Argv(1));
|
||||
r = Q_atof(Cmd_Argv(2));
|
||||
g = Q_atof(Cmd_Argv(3));
|
||||
b = Q_atof(Cmd_Argv(4));
|
||||
t = 0.0f;
|
||||
break;
|
||||
case 6: //TEST
|
||||
d = Q_atof(Cmd_Argv(1));
|
||||
r = Q_atof(Cmd_Argv(2));
|
||||
g = Q_atof(Cmd_Argv(3));
|
||||
b = Q_atof(Cmd_Argv(4));
|
||||
t = Q_atof(Cmd_Argv(5));
|
||||
break;
|
||||
}
|
||||
|
||||
if (d < 0.0f) d = 0.0f;
|
||||
if (r < 0.0f) r = 0.0f;
|
||||
else if (r > 1.0f) r = 1.0f;
|
||||
if (g < 0.0f) g = 0.0f;
|
||||
else if (g > 1.0f) g = 1.0f;
|
||||
if (b < 0.0f) b = 0.0f;
|
||||
else if (b > 1.0f) b = 1.0f;
|
||||
Fog_Update(d, r, g, b, t);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_ParseWorldspawn
|
||||
|
||||
called at map load
|
||||
=============
|
||||
*/
|
||||
void Fog_ParseWorldspawn (void)
|
||||
{
|
||||
char key[128], value[4096];
|
||||
const char *data;
|
||||
|
||||
//initially no fog
|
||||
fog_density = DEFAULT_DENSITY;
|
||||
fog_red = DEFAULT_GRAY;
|
||||
fog_green = DEFAULT_GRAY;
|
||||
fog_blue = DEFAULT_GRAY;
|
||||
|
||||
old_density = DEFAULT_DENSITY;
|
||||
old_red = DEFAULT_GRAY;
|
||||
old_green = DEFAULT_GRAY;
|
||||
old_blue = DEFAULT_GRAY;
|
||||
|
||||
fade_time = 0.0;
|
||||
fade_done = 0.0;
|
||||
|
||||
data = COM_Parse(cl.worldmodel->entities);
|
||||
if (!data)
|
||||
return; // error
|
||||
if (com_token[0] != '{')
|
||||
return; // error
|
||||
while (1)
|
||||
{
|
||||
data = COM_Parse(data);
|
||||
if (!data)
|
||||
return; // error
|
||||
if (com_token[0] == '}')
|
||||
break; // end of worldspawn
|
||||
if (com_token[0] == '_')
|
||||
q_strlcpy(key, com_token + 1, sizeof(key));
|
||||
else
|
||||
q_strlcpy(key, com_token, sizeof(key));
|
||||
while (key[0] && key[strlen(key)-1] == ' ') // remove trailing spaces
|
||||
key[strlen(key)-1] = 0;
|
||||
data = COM_ParseEx(data, CPE_ALLOWTRUNC);
|
||||
if (!data)
|
||||
return; // error
|
||||
q_strlcpy(value, com_token, sizeof(value));
|
||||
|
||||
if (!strcmp("fog", key))
|
||||
{
|
||||
sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_GetColor
|
||||
|
||||
calculates fog color for this frame, taking into account fade times
|
||||
=============
|
||||
*/
|
||||
float *Fog_GetColor (void)
|
||||
{
|
||||
static float c[4];
|
||||
float f;
|
||||
int i;
|
||||
|
||||
if (fade_done > cl.time)
|
||||
{
|
||||
f = (fade_done - cl.time) / fade_time;
|
||||
c[0] = f * old_red + (1.0 - f) * fog_red;
|
||||
c[1] = f * old_green + (1.0 - f) * fog_green;
|
||||
c[2] = f * old_blue + (1.0 - f) * fog_blue;
|
||||
c[3] = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c[0] = fog_red;
|
||||
c[1] = fog_green;
|
||||
c[2] = fog_blue;
|
||||
c[3] = 1.0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
c[i] = CLAMP (0.f, c[i], 1.f);
|
||||
}
|
||||
|
||||
//find closest 24-bit RGB value, so solid-colored sky can match the fog perfectly
|
||||
for (i = 0; i < 3; i++) {
|
||||
c[i] = (float)(Q_rint(c[i] * 255)) / 255.0f;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_GetDensity
|
||||
|
||||
returns current density of fog
|
||||
=============
|
||||
*/
|
||||
float Fog_GetDensity (void)
|
||||
{
|
||||
float f;
|
||||
|
||||
if (fade_done > cl.time)
|
||||
{
|
||||
f = (fade_done - cl.time) / fade_time;
|
||||
return f * old_density + (1.0 - f) * fog_density;
|
||||
}
|
||||
else
|
||||
return fog_density;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_SetupFrame
|
||||
|
||||
called at the beginning of each frame
|
||||
=============
|
||||
*/
|
||||
void Fog_SetupFrame (void)
|
||||
{
|
||||
glFogfv(GL_FOG_COLOR, Fog_GetColor());
|
||||
glFogf(GL_FOG_DENSITY, Fog_GetDensity() / 64.0);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_EnableGFog
|
||||
|
||||
called before drawing stuff that should be fogged
|
||||
=============
|
||||
*/
|
||||
void Fog_EnableGFog (void)
|
||||
{
|
||||
if (Fog_GetDensity() > 0)
|
||||
glEnable(GL_FOG);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_DisableGFog
|
||||
|
||||
called after drawing stuff that should be fogged
|
||||
=============
|
||||
*/
|
||||
void Fog_DisableGFog (void)
|
||||
{
|
||||
if (Fog_GetDensity() > 0)
|
||||
glDisable(GL_FOG);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_StartAdditive
|
||||
|
||||
called before drawing stuff that is additive blended -- sets fog color to black
|
||||
=============
|
||||
*/
|
||||
void Fog_StartAdditive (void)
|
||||
{
|
||||
vec3_t color = {0,0,0};
|
||||
|
||||
if (Fog_GetDensity() > 0)
|
||||
glFogfv(GL_FOG_COLOR, color);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_StopAdditive
|
||||
|
||||
called after drawing stuff that is additive blended -- restores fog color
|
||||
=============
|
||||
*/
|
||||
void Fog_StopAdditive (void)
|
||||
{
|
||||
if (Fog_GetDensity() > 0)
|
||||
glFogfv(GL_FOG_COLOR, Fog_GetColor());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// VOLUMETRIC FOG
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
cvar_t r_vfog = {"r_vfog", "1", CVAR_NONE};
|
||||
|
||||
void Fog_DrawVFog (void){}
|
||||
void Fog_MarkModels (void){}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// INIT
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_NewMap
|
||||
|
||||
called whenever a map is loaded
|
||||
=============
|
||||
*/
|
||||
void Fog_NewMap (void)
|
||||
{
|
||||
Fog_ParseWorldspawn (); //for global fog
|
||||
Fog_MarkModels (); //for volumetric fog
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_Init
|
||||
|
||||
called when quake initializes
|
||||
=============
|
||||
*/
|
||||
void Fog_Init (void)
|
||||
{
|
||||
Cmd_AddCommand ("fog",Fog_FogCommand_f);
|
||||
|
||||
//Cvar_RegisterVariable (&r_vfog);
|
||||
|
||||
//set up global fog
|
||||
fog_density = DEFAULT_DENSITY;
|
||||
fog_red = DEFAULT_GRAY;
|
||||
fog_green = DEFAULT_GRAY;
|
||||
fog_blue = DEFAULT_GRAY;
|
||||
|
||||
Fog_SetupState ();
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Fog_SetupState
|
||||
|
||||
ericw -- moved from Fog_Init, state that needs to be setup when a new context is created
|
||||
=============
|
||||
*/
|
||||
void Fog_SetupState (void)
|
||||
{
|
||||
glFogi(GL_FOG_MODE, GL_EXP2);
|
||||
}
|
||||
@@ -0,0 +1,603 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// gl_mesh.c: triangle model functions
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
|
||||
/*
|
||||
=================================================================
|
||||
|
||||
ALIAS MODEL DISPLAY LIST GENERATION
|
||||
|
||||
=================================================================
|
||||
*/
|
||||
|
||||
static unsigned char used[MAXALIASTRIS];
|
||||
|
||||
// the command list holds counts and s/t values that are valid for
|
||||
// every frame
|
||||
static int commands[MAXALIASTRIS*7 + 1];
|
||||
static int numcommands;
|
||||
|
||||
// all frames will have their vertexes rearranged and expanded
|
||||
// so they are in the order expected by the command list
|
||||
static int vertexorder[MAXALIASTRIS * 3];
|
||||
static int numorder;
|
||||
|
||||
static int stripverts[MAXALIASTRIS + 2];
|
||||
static int striptris[MAXALIASTRIS];
|
||||
static int stripcount;
|
||||
|
||||
/*
|
||||
================
|
||||
StripLength
|
||||
================
|
||||
*/
|
||||
static int StripLength (int starttri, int startv)
|
||||
{
|
||||
int m1, m2;
|
||||
int j;
|
||||
mtriangle_t *last, *check;
|
||||
int k;
|
||||
|
||||
used[starttri] = 2;
|
||||
|
||||
last = &triangles[starttri];
|
||||
|
||||
stripverts[0] = last->vertindex[(startv)%3];
|
||||
stripverts[1] = last->vertindex[(startv+1)%3];
|
||||
stripverts[2] = last->vertindex[(startv+2)%3];
|
||||
|
||||
striptris[0] = starttri;
|
||||
stripcount = 1;
|
||||
|
||||
m1 = last->vertindex[(startv+2)%3];
|
||||
m2 = last->vertindex[(startv+1)%3];
|
||||
|
||||
// look for a matching triangle
|
||||
nexttri:
|
||||
for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
|
||||
{
|
||||
if (check->facesfront != last->facesfront)
|
||||
continue;
|
||||
for (k=0 ; k<3 ; k++)
|
||||
{
|
||||
if (check->vertindex[k] != m1)
|
||||
continue;
|
||||
if (check->vertindex[ (k+1)%3 ] != m2)
|
||||
continue;
|
||||
|
||||
// this is the next part of the fan
|
||||
|
||||
// if we can't use this triangle, this tristrip is done
|
||||
if (used[j])
|
||||
goto done;
|
||||
|
||||
// the new edge
|
||||
if (stripcount & 1)
|
||||
m2 = check->vertindex[ (k+2)%3 ];
|
||||
else
|
||||
m1 = check->vertindex[ (k+2)%3 ];
|
||||
|
||||
stripverts[stripcount+2] = check->vertindex[ (k+2)%3 ];
|
||||
striptris[stripcount] = j;
|
||||
stripcount++;
|
||||
|
||||
used[j] = 2;
|
||||
goto nexttri;
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
// clear the temp used flags
|
||||
for (j=starttri+1 ; j<pheader->numtris ; j++)
|
||||
if (used[j] == 2)
|
||||
used[j] = 0;
|
||||
|
||||
return stripcount;
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
FanLength
|
||||
===========
|
||||
*/
|
||||
static int FanLength (int starttri, int startv)
|
||||
{
|
||||
int m1, m2;
|
||||
int j;
|
||||
mtriangle_t *last, *check;
|
||||
int k;
|
||||
|
||||
used[starttri] = 2;
|
||||
|
||||
last = &triangles[starttri];
|
||||
|
||||
stripverts[0] = last->vertindex[(startv)%3];
|
||||
stripverts[1] = last->vertindex[(startv+1)%3];
|
||||
stripverts[2] = last->vertindex[(startv+2)%3];
|
||||
|
||||
striptris[0] = starttri;
|
||||
stripcount = 1;
|
||||
|
||||
m1 = last->vertindex[(startv+0)%3];
|
||||
m2 = last->vertindex[(startv+2)%3];
|
||||
|
||||
|
||||
// look for a matching triangle
|
||||
nexttri:
|
||||
for (j=starttri+1, check=&triangles[starttri+1] ; j<pheader->numtris ; j++, check++)
|
||||
{
|
||||
if (check->facesfront != last->facesfront)
|
||||
continue;
|
||||
for (k=0 ; k<3 ; k++)
|
||||
{
|
||||
if (check->vertindex[k] != m1)
|
||||
continue;
|
||||
if (check->vertindex[ (k+1)%3 ] != m2)
|
||||
continue;
|
||||
|
||||
// this is the next part of the fan
|
||||
|
||||
// if we can't use this triangle, this tristrip is done
|
||||
if (used[j])
|
||||
goto done;
|
||||
|
||||
// the new edge
|
||||
m2 = check->vertindex[ (k+2)%3 ];
|
||||
|
||||
stripverts[stripcount+2] = m2;
|
||||
striptris[stripcount] = j;
|
||||
stripcount++;
|
||||
|
||||
used[j] = 2;
|
||||
goto nexttri;
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
// clear the temp used flags
|
||||
for (j=starttri+1 ; j<pheader->numtris ; j++)
|
||||
if (used[j] == 2)
|
||||
used[j] = 0;
|
||||
|
||||
return stripcount;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
BuildTris
|
||||
|
||||
Generate a list of trifans or strips
|
||||
for the model, which holds for all frames
|
||||
================
|
||||
*/
|
||||
static void BuildTris (void)
|
||||
{
|
||||
int i, j, k;
|
||||
int startv;
|
||||
float s, t;
|
||||
int len, bestlen, besttype;
|
||||
int bestverts[MAXALIASTRIS + 2];
|
||||
int besttris[MAXALIASTRIS];
|
||||
int type;
|
||||
|
||||
//
|
||||
// build tristrips
|
||||
//
|
||||
numorder = 0;
|
||||
numcommands = 0;
|
||||
memset (used, 0, sizeof(used));
|
||||
for (i = 0; i < pheader->numtris; i++)
|
||||
{
|
||||
// pick an unused triangle and start the trifan
|
||||
if (used[i])
|
||||
continue;
|
||||
|
||||
bestlen = 0;
|
||||
besttype = 0;
|
||||
for (type = 0 ; type < 2 ; type++)
|
||||
// type = 1;
|
||||
{
|
||||
for (startv = 0; startv < 3; startv++)
|
||||
{
|
||||
if (type == 1)
|
||||
len = StripLength (i, startv);
|
||||
else
|
||||
len = FanLength (i, startv);
|
||||
if (len > bestlen)
|
||||
{
|
||||
besttype = type;
|
||||
bestlen = len;
|
||||
for (j = 0; j < bestlen+2; j++)
|
||||
bestverts[j] = stripverts[j];
|
||||
for (j = 0; j < bestlen; j++)
|
||||
besttris[j] = striptris[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mark the tris on the best strip as used
|
||||
for (j = 0; j < bestlen; j++)
|
||||
used[besttris[j]] = 1;
|
||||
|
||||
if (besttype == 1)
|
||||
commands[numcommands++] = (bestlen+2);
|
||||
else
|
||||
commands[numcommands++] = -(bestlen+2);
|
||||
|
||||
for (j = 0; j < bestlen+2; j++)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
// emit a vertex into the reorder buffer
|
||||
k = bestverts[j];
|
||||
vertexorder[numorder++] = k;
|
||||
|
||||
// emit s/t coords into the commands stream
|
||||
s = stverts[k].s;
|
||||
t = stverts[k].t;
|
||||
if (!triangles[besttris[0]].facesfront && stverts[k].onseam)
|
||||
s += pheader->skinwidth / 2; // on back side
|
||||
s = (s + 0.5) / pheader->skinwidth;
|
||||
t = (t + 0.5) / pheader->skinheight;
|
||||
|
||||
// *(float *)&commands[numcommands++] = s;
|
||||
// *(float *)&commands[numcommands++] = t;
|
||||
// NOTE: 4 == sizeof(int)
|
||||
// == sizeof(float)
|
||||
memcpy (&tmp, &s, 4);
|
||||
commands[numcommands++] = tmp;
|
||||
memcpy (&tmp, &t, 4);
|
||||
commands[numcommands++] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
commands[numcommands++] = 0; // end of list marker
|
||||
|
||||
Con_DPrintf2 ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands);
|
||||
}
|
||||
|
||||
static void GL_MakeAliasModelDisplayLists_VBO (qmodel_t *, aliashdr_t *);
|
||||
static void GLMesh_LoadVertexBuffer (qmodel_t *m, const aliashdr_t *hdr);
|
||||
|
||||
/*
|
||||
================
|
||||
GL_MakeAliasModelDisplayLists
|
||||
================
|
||||
*/
|
||||
void GL_MakeAliasModelDisplayLists (qmodel_t *m, aliashdr_t *hdr)
|
||||
{
|
||||
int i, j;
|
||||
int *cmds;
|
||||
trivertx_t *verts;
|
||||
float hscale, vscale; //johnfitz -- padded skins
|
||||
int count; //johnfitz -- precompute texcoords for padded skins
|
||||
int *loadcmds; //johnfitz
|
||||
aliashdr_t *paliashdr = hdr; // (aliashdr_t *)Mod_Extradata (m);
|
||||
|
||||
//johnfitz -- padded skins
|
||||
hscale = (float)hdr->skinwidth/(float)TexMgr_PadConditional(hdr->skinwidth);
|
||||
vscale = (float)hdr->skinheight/(float)TexMgr_PadConditional(hdr->skinheight);
|
||||
//johnfitz
|
||||
|
||||
//johnfitz -- generate meshes
|
||||
Con_DPrintf2 ("meshing %s...\n",m->name);
|
||||
BuildTris ();
|
||||
|
||||
// save the data out
|
||||
|
||||
paliashdr->poseverts = numorder;
|
||||
|
||||
cmds = (int *) Hunk_Alloc (numcommands * 4);
|
||||
paliashdr->commands = (byte *)cmds - (byte *)paliashdr;
|
||||
|
||||
//johnfitz -- precompute texcoords for padded skins
|
||||
loadcmds = commands;
|
||||
while(1)
|
||||
{
|
||||
*cmds++ = count = *loadcmds++;
|
||||
|
||||
if (!count)
|
||||
break;
|
||||
|
||||
if (count < 0)
|
||||
count = -count;
|
||||
|
||||
do
|
||||
{
|
||||
*(float *)cmds++ = hscale * (*(float *)loadcmds++);
|
||||
*(float *)cmds++ = vscale * (*(float *)loadcmds++);
|
||||
} while (--count);
|
||||
}
|
||||
//johnfitz
|
||||
|
||||
verts = (trivertx_t *) Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts * sizeof(trivertx_t));
|
||||
paliashdr->posedata = (byte *)verts - (byte *)paliashdr;
|
||||
for (i=0 ; i<paliashdr->numposes ; i++)
|
||||
for (j=0 ; j<numorder ; j++)
|
||||
*verts++ = poseverts[i][vertexorder[j]];
|
||||
|
||||
// ericw
|
||||
GL_MakeAliasModelDisplayLists_VBO (m, paliashdr);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GL_MakeAliasModelDisplayLists_VBO
|
||||
|
||||
Saves data needed to build the VBO for this model on the hunk. Afterwards this
|
||||
is copied to Mod_Extradata.
|
||||
|
||||
Original code by MH from RMQEngine
|
||||
================
|
||||
*/
|
||||
static void GL_MakeAliasModelDisplayLists_VBO (qmodel_t *aliasmodel, aliashdr_t *paliashdr)
|
||||
{
|
||||
int i, j;
|
||||
int mark;
|
||||
trivertx_t *verts;
|
||||
unsigned short *indexes;
|
||||
unsigned short *remap;
|
||||
aliasmesh_t *desc;
|
||||
|
||||
if (!gl_glsl_alias_able)
|
||||
return;
|
||||
|
||||
// first, copy the verts onto the hunk
|
||||
verts = (trivertx_t *) Hunk_Alloc (paliashdr->numposes * paliashdr->numverts * sizeof(trivertx_t));
|
||||
paliashdr->vertexes = (byte *)verts - (byte *)paliashdr;
|
||||
for (i=0 ; i<paliashdr->numposes ; i++)
|
||||
for (j=0 ; j<paliashdr->numverts ; j++)
|
||||
verts[i*paliashdr->numverts + j] = poseverts[i][j];
|
||||
|
||||
// there can never be more than this number of verts and we just put them all on the hunk
|
||||
// (each vertex can be used twice, once with the original UVs and once with the seam adjustment)
|
||||
desc = (aliasmesh_t *) Hunk_Alloc (sizeof (aliasmesh_t) * pheader->numverts * 2);
|
||||
|
||||
// there will always be this number of indexes
|
||||
indexes = (unsigned short *) Hunk_Alloc (sizeof (unsigned short) * pheader->numtris * 3);
|
||||
|
||||
pheader->indexes = (intptr_t) indexes - (intptr_t) pheader;
|
||||
pheader->meshdesc = (intptr_t) desc - (intptr_t) pheader;
|
||||
pheader->numindexes = 0;
|
||||
pheader->numverts_vbo = 0;
|
||||
|
||||
mark = Hunk_LowMark ();
|
||||
|
||||
// each pair of elements in the remap array corresponds to one source vertex
|
||||
// each value is the final index + 1, or 0 if the corresponding vertex hasn't been emitted yet
|
||||
remap = (unsigned short *) Hunk_Alloc (paliashdr->numverts * 2 * sizeof (remap[0]));
|
||||
|
||||
for (i = 0; i < pheader->numtris; i++)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
// index into hdr->vertexes
|
||||
unsigned short vertindex = triangles[i].vertindex[j];
|
||||
|
||||
// index into remap table
|
||||
int v = vertindex * 2;
|
||||
|
||||
// check for back side
|
||||
if (!triangles[i].facesfront && stverts[vertindex].onseam)
|
||||
v++;
|
||||
|
||||
// emit new vertex if it doesn't already exist
|
||||
if (!remap[v])
|
||||
{
|
||||
// basic s/t coords
|
||||
int s = stverts[vertindex].s;
|
||||
int t = stverts[vertindex].t;
|
||||
|
||||
// check for back side and adjust texcoord s
|
||||
if (v & 1)
|
||||
s += paliashdr->skinwidth / 2;
|
||||
|
||||
desc[pheader->numverts_vbo].vertindex = vertindex;
|
||||
desc[pheader->numverts_vbo].st[0] = s;
|
||||
desc[pheader->numverts_vbo].st[1] = t;
|
||||
|
||||
remap[v] = ++pheader->numverts_vbo;
|
||||
}
|
||||
|
||||
// emit index
|
||||
indexes[pheader->numindexes++] = remap[v] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// free temporary data
|
||||
Hunk_FreeToLowMark (mark);
|
||||
|
||||
// upload immediately
|
||||
GLMesh_LoadVertexBuffer (aliasmodel, pheader);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GLMesh_LoadVertexBuffer
|
||||
|
||||
Upload the given alias model's mesh to a VBO
|
||||
|
||||
Original code by MH from RMQEngine
|
||||
================
|
||||
*/
|
||||
static void GLMesh_LoadVertexBuffer (qmodel_t *m, const aliashdr_t *hdr)
|
||||
{
|
||||
int totalvbosize = 0;
|
||||
const aliasmesh_t *desc;
|
||||
const short *indexes;
|
||||
const trivertx_t *trivertexes;
|
||||
byte *vbodata;
|
||||
int f;
|
||||
|
||||
if (!gl_glsl_alias_able)
|
||||
return;
|
||||
|
||||
// count the sizes we need
|
||||
|
||||
// ericw -- RMQEngine stored these vbo*ofs values in aliashdr_t, but we must not
|
||||
// mutate Mod_Extradata since it might be reloaded from disk, so I moved them to qmodel_t
|
||||
// (test case: roman1.bsp from arwop, 64mb heap)
|
||||
m->vboindexofs = 0;
|
||||
|
||||
m->vboxyzofs = 0;
|
||||
totalvbosize += (hdr->numposes * hdr->numverts_vbo * sizeof (meshxyz_t)); // ericw -- what RMQEngine called nummeshframes is called numposes in QuakeSpasm
|
||||
|
||||
m->vbostofs = totalvbosize;
|
||||
totalvbosize += (hdr->numverts_vbo * sizeof (meshst_t));
|
||||
|
||||
if (!hdr->numindexes) return;
|
||||
if (!totalvbosize) return;
|
||||
|
||||
// grab the pointers to data in the extradata
|
||||
|
||||
desc = (aliasmesh_t *) ((byte *) hdr + hdr->meshdesc);
|
||||
indexes = (short *) ((byte *) hdr + hdr->indexes);
|
||||
trivertexes = (trivertx_t *) ((byte *)hdr + hdr->vertexes);
|
||||
|
||||
// upload indices buffer
|
||||
|
||||
GL_DeleteBuffersFunc (1, &m->meshindexesvbo);
|
||||
GL_GenBuffersFunc (1, &m->meshindexesvbo);
|
||||
GL_BindBufferFunc (GL_ELEMENT_ARRAY_BUFFER, m->meshindexesvbo);
|
||||
GL_BufferDataFunc (GL_ELEMENT_ARRAY_BUFFER, hdr->numindexes * sizeof (unsigned short), indexes, GL_STATIC_DRAW);
|
||||
|
||||
// create the vertex buffer (empty)
|
||||
|
||||
vbodata = (byte *) malloc(totalvbosize);
|
||||
memset(vbodata, 0, totalvbosize);
|
||||
|
||||
// fill in the vertices at the start of the buffer
|
||||
for (f = 0; f < hdr->numposes; f++) // ericw -- what RMQEngine called nummeshframes is called numposes in QuakeSpasm
|
||||
{
|
||||
int v;
|
||||
meshxyz_t *xyz = (meshxyz_t *) (vbodata + (f * hdr->numverts_vbo * sizeof (meshxyz_t)));
|
||||
const trivertx_t *tv = trivertexes + (hdr->numverts * f);
|
||||
|
||||
for (v = 0; v < hdr->numverts_vbo; v++)
|
||||
{
|
||||
trivertx_t trivert = tv[desc[v].vertindex];
|
||||
|
||||
xyz[v].xyz[0] = trivert.v[0];
|
||||
xyz[v].xyz[1] = trivert.v[1];
|
||||
xyz[v].xyz[2] = trivert.v[2];
|
||||
xyz[v].xyz[3] = 1; // need w 1 for 4 byte vertex compression
|
||||
|
||||
// map the normal coordinates in [-1..1] to [-127..127] and store in an unsigned char.
|
||||
// this introduces some error (less than 0.004), but the normals were very coarse
|
||||
// to begin with
|
||||
xyz[v].normal[0] = 127 * r_avertexnormals[trivert.lightnormalindex][0];
|
||||
xyz[v].normal[1] = 127 * r_avertexnormals[trivert.lightnormalindex][1];
|
||||
xyz[v].normal[2] = 127 * r_avertexnormals[trivert.lightnormalindex][2];
|
||||
xyz[v].normal[3] = 0; // unused; for 4-byte alignment
|
||||
}
|
||||
}
|
||||
|
||||
// fill in the ST coords at the end of the buffer
|
||||
{
|
||||
meshst_t *st;
|
||||
float hscale, vscale;
|
||||
|
||||
//johnfitz -- padded skins
|
||||
hscale = 1.0f / (float)TexMgr_PadConditional(hdr->skinwidth);
|
||||
vscale = 1.0f / (float)TexMgr_PadConditional(hdr->skinheight);
|
||||
//johnfitz
|
||||
|
||||
st = (meshst_t *) (vbodata + m->vbostofs);
|
||||
for (f = 0; f < hdr->numverts_vbo; f++)
|
||||
{
|
||||
st[f].st[0] = hscale * ((float) desc[f].st[0] + 0.5f);
|
||||
st[f].st[1] = vscale * ((float) desc[f].st[1] + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// upload vertexes buffer
|
||||
GL_DeleteBuffersFunc (1, &m->meshvbo);
|
||||
GL_GenBuffersFunc (1, &m->meshvbo);
|
||||
GL_BindBufferFunc (GL_ARRAY_BUFFER, m->meshvbo);
|
||||
GL_BufferDataFunc (GL_ARRAY_BUFFER, totalvbosize, vbodata, GL_STATIC_DRAW);
|
||||
|
||||
free (vbodata);
|
||||
|
||||
// invalidate the cached bindings
|
||||
GL_ClearBufferBindings ();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GLMesh_LoadVertexBuffers
|
||||
|
||||
Loop over all precached alias models, and upload each one to a VBO.
|
||||
================
|
||||
*/
|
||||
void GLMesh_LoadVertexBuffers (void)
|
||||
{
|
||||
int j;
|
||||
qmodel_t *m;
|
||||
const aliashdr_t *hdr;
|
||||
|
||||
if (!gl_glsl_alias_able)
|
||||
return;
|
||||
|
||||
for (j = 1; j < MAX_MODELS; j++)
|
||||
{
|
||||
if (!(m = cl.model_precache[j])) break;
|
||||
if (m->type != mod_alias) continue;
|
||||
|
||||
hdr = (const aliashdr_t *) Mod_Extradata (m);
|
||||
|
||||
GLMesh_LoadVertexBuffer (m, hdr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GLMesh_DeleteVertexBuffers
|
||||
|
||||
Delete VBOs for all loaded alias models
|
||||
================
|
||||
*/
|
||||
void GLMesh_DeleteVertexBuffers (void)
|
||||
{
|
||||
int j;
|
||||
qmodel_t *m;
|
||||
|
||||
if (!gl_glsl_alias_able)
|
||||
return;
|
||||
|
||||
for (j = 1; j < MAX_MODELS; j++)
|
||||
{
|
||||
if (!(m = cl.model_precache[j])) break;
|
||||
if (m->type != mod_alias) continue;
|
||||
|
||||
GL_DeleteBuffersFunc (1, &m->meshvbo);
|
||||
m->meshvbo = 0;
|
||||
|
||||
GL_DeleteBuffersFunc (1, &m->meshindexesvbo);
|
||||
m->meshindexesvbo = 0;
|
||||
}
|
||||
|
||||
GL_ClearBufferBindings ();
|
||||
}
|
||||
+3094
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,520 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 GL_MODEL_H
|
||||
#define GL_MODEL_H
|
||||
|
||||
#include "modelgen.hpp"
|
||||
#include "spritegn.hpp"
|
||||
|
||||
/*
|
||||
|
||||
d*_t structures are on-disk representations
|
||||
m*_t structures are in-memory
|
||||
|
||||
*/
|
||||
|
||||
// entity effects
|
||||
|
||||
#define EF_BRIGHTFIELD 1
|
||||
#define EF_MUZZLEFLASH 2
|
||||
#define EF_BRIGHTLIGHT 4
|
||||
#define EF_DIMLIGHT 8
|
||||
#define EF_QEX_QUADLIGHT 16 // 2021 rerelease
|
||||
#define EF_QEX_PENTALIGHT 32 // 2021 rerelease
|
||||
#define EF_QEX_CANDLELIGHT 64 // 2021 rerelease
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
BRUSH MODELS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
// in memory representation
|
||||
//
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct
|
||||
{
|
||||
vec3_t position;
|
||||
} mvertex_t;
|
||||
|
||||
#define SIDE_FRONT 0
|
||||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
|
||||
|
||||
// plane_t structure
|
||||
// !!! if this is changed, it must be changed in asm_i386.h too !!!
|
||||
typedef struct mplane_s
|
||||
{
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
byte type; // for texture axis selection and fast side tests
|
||||
byte signbits; // signx + signy<<1 + signz<<1
|
||||
byte pad[2];
|
||||
} mplane_t;
|
||||
|
||||
// ericw -- each texture has two chains, so we can clear the model chains
|
||||
// without affecting the world
|
||||
typedef enum {
|
||||
chain_world = 0,
|
||||
chain_model = 1
|
||||
} texchain_t;
|
||||
|
||||
typedef struct texture_s
|
||||
{
|
||||
char name[16];
|
||||
unsigned width, height;
|
||||
unsigned shift; // Q64
|
||||
struct gltexture_s *gltexture; //johnfitz -- pointer to gltexture
|
||||
struct gltexture_s *fullbright; //johnfitz -- fullbright mask texture
|
||||
struct gltexture_s *warpimage; //johnfitz -- for water animation
|
||||
qboolean update_warp; //johnfitz -- update warp this frame
|
||||
struct msurface_s *texturechains[2]; // for texture chains
|
||||
int anim_total; // total tenths in sequence ( 0 = no)
|
||||
int anim_min, anim_max; // time for this frame min <=time< max
|
||||
struct texture_s *anim_next; // in the animation sequence
|
||||
struct texture_s *alternate_anims; // bmodels in frmae 1 use these
|
||||
} texture_t;
|
||||
|
||||
|
||||
#define SURF_PLANEBACK 2
|
||||
#define SURF_DRAWSKY 4
|
||||
#define SURF_DRAWSPRITE 8
|
||||
#define SURF_DRAWTURB 0x10
|
||||
#define SURF_DRAWTILED 0x20
|
||||
#define SURF_DRAWBACKGROUND 0x40
|
||||
#define SURF_UNDERWATER 0x80
|
||||
#define SURF_NOTEXTURE 0x100 //johnfitz
|
||||
#define SURF_DRAWFENCE 0x200
|
||||
#define SURF_DRAWLAVA 0x400
|
||||
#define SURF_DRAWSLIME 0x800
|
||||
#define SURF_DRAWTELE 0x1000
|
||||
#define SURF_DRAWWATER 0x2000
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct
|
||||
{
|
||||
unsigned int v[2];
|
||||
unsigned int cachededgeoffset;
|
||||
} medge_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float vecs[2][4];
|
||||
texture_t *texture;
|
||||
int flags;
|
||||
} mtexinfo_t;
|
||||
|
||||
#define VERTEXSIZE 7
|
||||
|
||||
typedef struct glpoly_s
|
||||
{
|
||||
struct glpoly_s *next;
|
||||
struct glpoly_s *chain;
|
||||
int numverts;
|
||||
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
||||
} glpoly_t;
|
||||
|
||||
typedef struct msurface_s
|
||||
{
|
||||
int visframe; // should be drawn when node is crossed
|
||||
float mins[3]; // johnfitz -- for frustum culling
|
||||
float maxs[3]; // johnfitz -- for frustum culling
|
||||
|
||||
mplane_t *plane;
|
||||
int flags;
|
||||
|
||||
int firstedge; // look up in model->surfedges[], negative numbers
|
||||
int numedges; // are backwards edges
|
||||
|
||||
short texturemins[2];
|
||||
short extents[2];
|
||||
|
||||
int light_s, light_t; // gl lightmap coordinates
|
||||
|
||||
glpoly_t *polys; // multiple if warped
|
||||
struct msurface_s *texturechain;
|
||||
|
||||
mtexinfo_t *texinfo;
|
||||
|
||||
int vbo_firstvert; // index of this surface's first vert in the VBO
|
||||
|
||||
// lighting info
|
||||
int dlightframe;
|
||||
unsigned int dlightbits[(MAX_DLIGHTS + 31) >> 5];
|
||||
// int is 32 bits, need an array for MAX_DLIGHTS > 32
|
||||
|
||||
int lightmaptexturenum;
|
||||
byte styles[MAXLIGHTMAPS];
|
||||
int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap
|
||||
qboolean cached_dlight; // true if dynamic light in cache
|
||||
byte *samples; // [numstyles*surfsize]
|
||||
} msurface_t;
|
||||
|
||||
typedef struct mnode_s
|
||||
{
|
||||
// common with leaf
|
||||
int contents; // 0, to differentiate from leafs
|
||||
int visframe; // node needs to be traversed if current
|
||||
|
||||
float minmaxs[6]; // for bounding box culling
|
||||
|
||||
struct mnode_s *parent;
|
||||
|
||||
// node specific
|
||||
mplane_t *plane;
|
||||
struct mnode_s *children[2];
|
||||
|
||||
unsigned int firstsurface;
|
||||
unsigned int numsurfaces;
|
||||
} mnode_t;
|
||||
|
||||
|
||||
|
||||
typedef struct mleaf_s
|
||||
{
|
||||
// common with node
|
||||
int contents; // wil be a negative contents number
|
||||
int visframe; // node needs to be traversed if current
|
||||
|
||||
float minmaxs[6]; // for bounding box culling
|
||||
|
||||
struct mnode_s *parent;
|
||||
|
||||
// leaf specific
|
||||
byte *compressed_vis;
|
||||
efrag_t *efrags;
|
||||
|
||||
msurface_t **firstmarksurface;
|
||||
int nummarksurfaces;
|
||||
int key; // BSP sequence number for leaf's contents
|
||||
byte ambient_sound_level[NUM_AMBIENTS];
|
||||
} mleaf_t;
|
||||
|
||||
//johnfitz -- for clipnodes>32k
|
||||
typedef struct mclipnode_s
|
||||
{
|
||||
int planenum;
|
||||
int children[2]; // negative numbers are contents
|
||||
} mclipnode_t;
|
||||
//johnfitz
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_i386.h too !!!
|
||||
typedef struct
|
||||
{
|
||||
mclipnode_t *clipnodes; //johnfitz -- was dclipnode_t
|
||||
mplane_t *planes;
|
||||
int firstclipnode;
|
||||
int lastclipnode;
|
||||
vec3_t clip_mins;
|
||||
vec3_t clip_maxs;
|
||||
} hull_t;
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
SPRITE MODELS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
// FIXME: shorten these?
|
||||
typedef struct mspriteframe_s
|
||||
{
|
||||
int width, height;
|
||||
float up, down, left, right;
|
||||
float smax, tmax; //johnfitz -- image might be padded
|
||||
struct gltexture_s *gltexture;
|
||||
} mspriteframe_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numframes;
|
||||
float *intervals;
|
||||
mspriteframe_t *frames[1];
|
||||
} mspritegroup_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
spriteframetype_t type;
|
||||
mspriteframe_t *frameptr;
|
||||
} mspriteframedesc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
int maxwidth;
|
||||
int maxheight;
|
||||
int numframes;
|
||||
float beamlength; // remove?
|
||||
void *cachespot; // remove?
|
||||
mspriteframedesc_t frames[1];
|
||||
} msprite_t;
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
ALIAS MODELS
|
||||
|
||||
Alias models are position independent, so the cache manager can move them.
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//-- from RMQEngine
|
||||
// split out to keep vertex sizes down
|
||||
typedef struct aliasmesh_s
|
||||
{
|
||||
float st[2];
|
||||
unsigned short vertindex;
|
||||
} aliasmesh_t;
|
||||
|
||||
typedef struct meshxyz_s
|
||||
{
|
||||
byte xyz[4];
|
||||
signed char normal[4];
|
||||
} meshxyz_t;
|
||||
|
||||
typedef struct meshst_s
|
||||
{
|
||||
float st[2];
|
||||
} meshst_t;
|
||||
//--
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int firstpose;
|
||||
int numposes;
|
||||
float interval;
|
||||
trivertx_t bboxmin;
|
||||
trivertx_t bboxmax;
|
||||
int frame;
|
||||
char name[16];
|
||||
} maliasframedesc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
trivertx_t bboxmin;
|
||||
trivertx_t bboxmax;
|
||||
int frame;
|
||||
} maliasgroupframedesc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numframes;
|
||||
int intervals;
|
||||
maliasgroupframedesc_t frames[1];
|
||||
} maliasgroup_t;
|
||||
|
||||
// !!! if this is changed, it must be changed in asm_draw.h too !!!
|
||||
typedef struct mtriangle_s {
|
||||
int facesfront;
|
||||
int vertindex[3];
|
||||
} mtriangle_t;
|
||||
|
||||
|
||||
#define MAX_SKINS 32
|
||||
typedef struct {
|
||||
int ident;
|
||||
int version;
|
||||
vec3_t scale;
|
||||
vec3_t scale_origin;
|
||||
float boundingradius;
|
||||
vec3_t eyeposition;
|
||||
int numskins;
|
||||
int skinwidth;
|
||||
int skinheight;
|
||||
int numverts;
|
||||
int numtris;
|
||||
int numframes;
|
||||
synctype_t synctype;
|
||||
int flags;
|
||||
float size;
|
||||
|
||||
//ericw -- used to populate vbo
|
||||
int numverts_vbo; // number of verts with unique x,y,z,s,t
|
||||
intptr_t meshdesc; // offset into extradata: numverts_vbo aliasmesh_t
|
||||
int numindexes;
|
||||
intptr_t indexes; // offset into extradata: numindexes unsigned shorts
|
||||
intptr_t vertexes; // offset into extradata: numposes*vertsperframe trivertx_t
|
||||
//ericw --
|
||||
|
||||
int numposes;
|
||||
int poseverts;
|
||||
int posedata; // numposes*poseverts trivert_t
|
||||
int commands; // gl command list with embedded s/t
|
||||
struct gltexture_s *gltextures[MAX_SKINS][4]; //johnfitz
|
||||
struct gltexture_s *fbtextures[MAX_SKINS][4]; //johnfitz
|
||||
int texels[MAX_SKINS]; // only for player skins
|
||||
maliasframedesc_t frames[1]; // variable sized
|
||||
} aliashdr_t;
|
||||
|
||||
#define MAXALIASVERTS 2000 //johnfitz -- was 1024
|
||||
#define MAXALIASFRAMES 1024 //spike -- was 256
|
||||
#define MAXALIASTRIS 4096 //ericw -- was 2048
|
||||
extern aliashdr_t *pheader;
|
||||
extern stvert_t stverts[MAXALIASVERTS];
|
||||
extern mtriangle_t triangles[MAXALIASTRIS];
|
||||
extern trivertx_t *poseverts[MAXALIASFRAMES];
|
||||
|
||||
//===================================================================
|
||||
|
||||
//
|
||||
// Whole model
|
||||
//
|
||||
|
||||
typedef enum {mod_brush, mod_sprite, mod_alias} modtype_t;
|
||||
|
||||
#define EF_ROCKET 1 // leave a trail
|
||||
#define EF_GRENADE 2 // leave a trail
|
||||
#define EF_GIB 4 // leave a trail
|
||||
#define EF_ROTATE 8 // rotate (bonus items)
|
||||
#define EF_TRACER 16 // green split trail
|
||||
#define EF_ZOMGIB 32 // small blood trail
|
||||
#define EF_TRACER2 64 // orange split trail + rotate
|
||||
#define EF_TRACER3 128 // purple trail
|
||||
#define MF_HOLEY (1u<<14) // MarkV/QSS -- make index 255 transparent on mdl's
|
||||
|
||||
//johnfitz -- extra flags for rendering
|
||||
#define MOD_NOLERP 256 //don't lerp when animating
|
||||
#define MOD_NOSHADOW 512 //don't cast a shadow
|
||||
#define MOD_FBRIGHTHACK 1024 //when fullbrights are disabled, use a hack to render this model brighter
|
||||
//johnfitz
|
||||
|
||||
typedef struct qmodel_s
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
unsigned int path_id; // path id of the game directory
|
||||
// that this model came from
|
||||
qboolean needload; // bmodels and sprites don't cache normally
|
||||
|
||||
modtype_t type;
|
||||
int numframes;
|
||||
synctype_t synctype;
|
||||
|
||||
int flags;
|
||||
|
||||
//
|
||||
// volume occupied by the model graphics
|
||||
//
|
||||
vec3_t mins, maxs;
|
||||
vec3_t ymins, ymaxs; //johnfitz -- bounds for entities with nonzero yaw
|
||||
vec3_t rmins, rmaxs; //johnfitz -- bounds for entities with nonzero pitch or roll
|
||||
//johnfitz -- removed float radius;
|
||||
|
||||
//
|
||||
// solid volume for clipping
|
||||
//
|
||||
qboolean clipbox;
|
||||
vec3_t clipmins, clipmaxs;
|
||||
|
||||
//
|
||||
// brush model
|
||||
//
|
||||
int firstmodelsurface, nummodelsurfaces;
|
||||
|
||||
int numsubmodels;
|
||||
dmodel_t *submodels;
|
||||
|
||||
int numplanes;
|
||||
mplane_t *planes;
|
||||
|
||||
int numleafs; // number of visible leafs, not counting 0
|
||||
mleaf_t *leafs;
|
||||
|
||||
int numvertexes;
|
||||
mvertex_t *vertexes;
|
||||
|
||||
int numedges;
|
||||
medge_t *edges;
|
||||
|
||||
int numnodes;
|
||||
mnode_t *nodes;
|
||||
|
||||
int numtexinfo;
|
||||
mtexinfo_t *texinfo;
|
||||
|
||||
int numsurfaces;
|
||||
msurface_t *surfaces;
|
||||
|
||||
int numsurfedges;
|
||||
int *surfedges;
|
||||
|
||||
int numclipnodes;
|
||||
mclipnode_t *clipnodes; //johnfitz -- was dclipnode_t
|
||||
|
||||
int nummarksurfaces;
|
||||
msurface_t **marksurfaces;
|
||||
|
||||
hull_t hulls[MAX_MAP_HULLS];
|
||||
|
||||
int numtextures;
|
||||
texture_t **textures;
|
||||
|
||||
byte *visdata;
|
||||
byte *lightdata;
|
||||
char *entities;
|
||||
|
||||
qboolean viswarn; // for Mod_DecompressVis()
|
||||
|
||||
int bspversion;
|
||||
qboolean haslitwater;
|
||||
//
|
||||
// alias model
|
||||
//
|
||||
|
||||
GLuint meshvbo;
|
||||
GLuint meshindexesvbo;
|
||||
int vboindexofs; // offset in vbo of the hdr->numindexes unsigned shorts
|
||||
int vboxyzofs; // offset in vbo of hdr->numposes*hdr->numverts_vbo meshxyz_t
|
||||
int vbostofs; // offset in vbo of hdr->numverts_vbo meshst_t
|
||||
|
||||
//
|
||||
// additional model data
|
||||
//
|
||||
cache_user_t cache; // only access through Mod_Extradata
|
||||
|
||||
} qmodel_t;
|
||||
|
||||
//============================================================================
|
||||
|
||||
void Mod_Init (void);
|
||||
void Mod_ClearAll (void);
|
||||
void Mod_ResetAll (void); // for gamedir changes (Host_Game_f)
|
||||
qmodel_t *Mod_ForName (const char *name, qboolean crash);
|
||||
void *Mod_Extradata (qmodel_t *mod); // handles caching
|
||||
void Mod_TouchModel (const char *name);
|
||||
|
||||
mleaf_t *Mod_PointInLeaf (vec3_t p, qmodel_t *model);
|
||||
byte *Mod_LeafPVS (mleaf_t *leaf, qmodel_t *model);
|
||||
byte *Mod_NoVisPVS (qmodel_t *model);
|
||||
|
||||
void Mod_SetExtraFlags (qmodel_t *mod);
|
||||
|
||||
#endif /* GL_MODEL_H */
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// r_efrag.c
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
static mnode_t *r_pefragtopnode;
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
ENTITY FRAGMENT FUNCTIONS
|
||||
|
||||
ericw -- GLQuake only uses efrags for static entities, and they're never
|
||||
removed, so I trimmed out unused functionality and fields in efrag_t.
|
||||
|
||||
Now, efrags are just a linked list for each leaf of the static
|
||||
entities that touch that leaf. The efrags are hunk-allocated so there is no
|
||||
fixed limit.
|
||||
|
||||
This is inspired by MH's tutorial, and code from RMQEngine.
|
||||
http://forums.insideqc.com/viewtopic.php?t=1930
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
static vec3_t r_emins, r_emaxs;
|
||||
|
||||
static entity_t *r_addent;
|
||||
|
||||
|
||||
#define EXTRA_EFRAGS 128
|
||||
|
||||
// based on RMQEngine
|
||||
static efrag_t *R_GetEfrag (void)
|
||||
{
|
||||
// we could just Hunk_Alloc a single efrag_t and return it, but since
|
||||
// the struct is so small (2 pointers) allocate groups of them
|
||||
// to avoid wasting too much space on the hunk allocation headers.
|
||||
if (cl.free_efrags)
|
||||
{
|
||||
efrag_t *ef = cl.free_efrags;
|
||||
cl.free_efrags = ef->leafnext;
|
||||
ef->leafnext = NULL;
|
||||
|
||||
cl.num_efrags++;
|
||||
|
||||
return ef;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
cl.free_efrags = (efrag_t *) Hunk_AllocName (EXTRA_EFRAGS * sizeof (efrag_t), "efrags");
|
||||
|
||||
for (i = 0; i < EXTRA_EFRAGS - 1; i++)
|
||||
cl.free_efrags[i].leafnext = &cl.free_efrags[i + 1];
|
||||
|
||||
cl.free_efrags[i].leafnext = NULL;
|
||||
|
||||
// call recursively to get a newly allocated free efrag
|
||||
return R_GetEfrag ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
R_SplitEntityOnNode
|
||||
===================
|
||||
*/
|
||||
void R_SplitEntityOnNode (mnode_t *node)
|
||||
{
|
||||
efrag_t *ef;
|
||||
mplane_t *splitplane;
|
||||
mleaf_t *leaf;
|
||||
int sides;
|
||||
|
||||
if (node->contents == CONTENTS_SOLID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// add an efrag if the node is a leaf
|
||||
|
||||
if ( node->contents < 0)
|
||||
{
|
||||
if (!r_pefragtopnode)
|
||||
r_pefragtopnode = node;
|
||||
|
||||
leaf = (mleaf_t *)node;
|
||||
|
||||
// grab an efrag off the free list
|
||||
ef = R_GetEfrag();
|
||||
ef->entity = r_addent;
|
||||
|
||||
// set the leaf links
|
||||
ef->leafnext = leaf->efrags;
|
||||
leaf->efrags = ef;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// NODE_MIXED
|
||||
|
||||
splitplane = node->plane;
|
||||
sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);
|
||||
|
||||
if (sides == 3)
|
||||
{
|
||||
// split on this plane
|
||||
// if this is the first splitter of this bmodel, remember it
|
||||
if (!r_pefragtopnode)
|
||||
r_pefragtopnode = node;
|
||||
}
|
||||
|
||||
// recurse down the contacted sides
|
||||
if (sides & 1)
|
||||
R_SplitEntityOnNode (node->children[0]);
|
||||
|
||||
if (sides & 2)
|
||||
R_SplitEntityOnNode (node->children[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
R_CheckEfrags -- johnfitz -- check for excessive efrag count
|
||||
===========
|
||||
*/
|
||||
void R_CheckEfrags (void)
|
||||
{
|
||||
if (cls.signon < 2)
|
||||
return; //don't spam when still parsing signon packet full of static ents
|
||||
|
||||
if (cl.num_efrags > 640 && dev_peakstats.efrags <= 640)
|
||||
Con_DWarning ("%i efrags exceeds standard limit of 640.\n", cl.num_efrags);
|
||||
|
||||
dev_stats.efrags = cl.num_efrags;
|
||||
dev_peakstats.efrags = q_max(cl.num_efrags, dev_peakstats.efrags);
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
R_AddEfrags
|
||||
===========
|
||||
*/
|
||||
void R_AddEfrags (entity_t *ent)
|
||||
{
|
||||
qmodel_t *entmodel;
|
||||
vec_t scalefactor;
|
||||
|
||||
if (!ent->model)
|
||||
return;
|
||||
|
||||
r_addent = ent;
|
||||
|
||||
r_pefragtopnode = NULL;
|
||||
|
||||
entmodel = ent->model;
|
||||
scalefactor = ENTSCALE_DECODE(ent->scale);
|
||||
if (scalefactor != 1.0f)
|
||||
{
|
||||
VectorMA (ent->origin, scalefactor, entmodel->mins, r_emins);
|
||||
VectorMA (ent->origin, scalefactor, entmodel->maxs, r_emaxs);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorAdd (ent->origin, entmodel->mins, r_emins);
|
||||
VectorAdd (ent->origin, entmodel->maxs, r_emaxs);
|
||||
}
|
||||
|
||||
R_SplitEntityOnNode (cl.worldmodel->nodes);
|
||||
|
||||
ent->topnode = r_pefragtopnode;
|
||||
|
||||
R_CheckEfrags (); //johnfitz
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_StoreEfrags -- johnfitz -- pointless switch statement removed.
|
||||
================
|
||||
*/
|
||||
void R_StoreEfrags (efrag_t **ppefrag)
|
||||
{
|
||||
entity_t *pent;
|
||||
efrag_t *pefrag;
|
||||
|
||||
while ((pefrag = *ppefrag) != NULL)
|
||||
{
|
||||
pent = pefrag->entity;
|
||||
|
||||
if ((pent->visframe != r_framecount) && (cl_numvisedicts < MAX_VISEDICTS))
|
||||
{
|
||||
cl_visedicts[cl_numvisedicts++] = pent;
|
||||
pent->visframe = r_framecount;
|
||||
}
|
||||
|
||||
ppefrag = &pefrag->leafnext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// r_light.c
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
static int r_dlightframecount;
|
||||
|
||||
extern cvar_t r_flatlightstyles; //johnfitz
|
||||
|
||||
/*
|
||||
==================
|
||||
R_AnimateLight
|
||||
==================
|
||||
*/
|
||||
void R_AnimateLight (void)
|
||||
{
|
||||
int i,j,k;
|
||||
|
||||
//
|
||||
// light animations
|
||||
// 'm' is normal light, 'a' is no light, 'z' is double bright
|
||||
i = (int)(cl.time*10);
|
||||
for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
|
||||
{
|
||||
if (!cl_lightstyle[j].length)
|
||||
{
|
||||
d_lightstylevalue[j] = 256;
|
||||
continue;
|
||||
}
|
||||
//johnfitz -- r_flatlightstyles
|
||||
if (r_flatlightstyles.value == 2)
|
||||
k = cl_lightstyle[j].peak - 'a';
|
||||
else if (r_flatlightstyles.value == 1)
|
||||
k = cl_lightstyle[j].average - 'a';
|
||||
else
|
||||
{
|
||||
k = i % cl_lightstyle[j].length;
|
||||
k = cl_lightstyle[j].map[k] - 'a';
|
||||
}
|
||||
d_lightstylevalue[j] = k*22;
|
||||
//johnfitz
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
DYNAMIC LIGHTS BLEND RENDERING (gl_flashblend 1)
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
void AddLightBlend (float r, float g, float b, float a2)
|
||||
{
|
||||
float a;
|
||||
|
||||
v_blend[3] = a = v_blend[3] + a2*(1-v_blend[3]);
|
||||
|
||||
a2 = a2/a;
|
||||
|
||||
v_blend[0] = v_blend[1]*(1-a2) + r*a2;
|
||||
v_blend[1] = v_blend[1]*(1-a2) + g*a2;
|
||||
v_blend[2] = v_blend[2]*(1-a2) + b*a2;
|
||||
}
|
||||
|
||||
void R_RenderDlight (dlight_t *light)
|
||||
{
|
||||
int i, j;
|
||||
float a;
|
||||
vec3_t v;
|
||||
float rad;
|
||||
|
||||
rad = light->radius * 0.35;
|
||||
|
||||
VectorSubtract (light->origin, r_origin, v);
|
||||
if (VectorLength (v) < rad)
|
||||
{ // view is inside the dlight
|
||||
AddLightBlend (1, 0.5, 0, light->radius * 0.0003);
|
||||
return;
|
||||
}
|
||||
|
||||
glBegin (GL_TRIANGLE_FAN);
|
||||
glColor3f (0.2,0.1,0.0);
|
||||
for (i=0 ; i<3 ; i++)
|
||||
v[i] = light->origin[i] - vpn[i]*rad;
|
||||
glVertex3fv (v);
|
||||
glColor3f (0,0,0);
|
||||
for (i=16 ; i>=0 ; i--)
|
||||
{
|
||||
a = i/16.0 * M_PI*2;
|
||||
for (j=0 ; j<3 ; j++)
|
||||
v[j] = light->origin[j] + vright[j]*cos(a)*rad
|
||||
+ vup[j]*sin(a)*rad;
|
||||
glVertex3fv (v);
|
||||
}
|
||||
glEnd ();
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_RenderDlights
|
||||
=============
|
||||
*/
|
||||
void R_RenderDlights (void)
|
||||
{
|
||||
int i;
|
||||
dlight_t *l;
|
||||
|
||||
if (!gl_flashblend.value)
|
||||
return;
|
||||
|
||||
r_dlightframecount = r_framecount + 1; // because the count hasn't advanced yet for this frame
|
||||
glDepthMask (0);
|
||||
glDisable (GL_TEXTURE_2D);
|
||||
glShadeModel (GL_SMOOTH);
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_ONE, GL_ONE);
|
||||
|
||||
l = cl_dlights;
|
||||
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
|
||||
{
|
||||
if (l->die < cl.time || !l->radius)
|
||||
continue;
|
||||
R_RenderDlight (l);
|
||||
}
|
||||
|
||||
glColor3f (1,1,1);
|
||||
glDisable (GL_BLEND);
|
||||
glEnable (GL_TEXTURE_2D);
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthMask (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
DYNAMIC LIGHTS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=============
|
||||
R_MarkLights -- johnfitz -- rewritten to use LordHavoc's lighting speedup
|
||||
=============
|
||||
*/
|
||||
void R_MarkLights (dlight_t *light, int num, mnode_t *node)
|
||||
{
|
||||
mplane_t *splitplane;
|
||||
msurface_t *surf;
|
||||
vec3_t impact;
|
||||
float dist, l, maxdist;
|
||||
int i, j, s, t;
|
||||
|
||||
start:
|
||||
if (node->contents < 0)
|
||||
return;
|
||||
|
||||
splitplane = node->plane;
|
||||
if (splitplane->type < 3)
|
||||
dist = light->origin[splitplane->type] - splitplane->dist;
|
||||
else
|
||||
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
|
||||
|
||||
if (dist > light->radius)
|
||||
{
|
||||
node = node->children[0];
|
||||
goto start;
|
||||
}
|
||||
if (dist < -light->radius)
|
||||
{
|
||||
node = node->children[1];
|
||||
goto start;
|
||||
}
|
||||
|
||||
maxdist = light->radius*light->radius;
|
||||
// mark the polygons
|
||||
surf = cl.worldmodel->surfaces + node->firstsurface;
|
||||
for (i=0 ; i<node->numsurfaces ; i++, surf++)
|
||||
{
|
||||
for (j=0 ; j<3 ; j++)
|
||||
impact[j] = light->origin[j] - surf->plane->normal[j]*dist;
|
||||
// clamp center of light to corner and check brightness
|
||||
l = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
|
||||
s = l+0.5;if (s < 0) s = 0;else if (s > surf->extents[0]) s = surf->extents[0];
|
||||
s = l - s;
|
||||
l = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
|
||||
t = l+0.5;if (t < 0) t = 0;else if (t > surf->extents[1]) t = surf->extents[1];
|
||||
t = l - t;
|
||||
// compare to minimum light
|
||||
if ((s*s+t*t+dist*dist) < maxdist)
|
||||
{
|
||||
if (surf->dlightframe != r_dlightframecount) // not dynamic until now
|
||||
{
|
||||
surf->dlightbits[num >> 5] = 1U << (num & 31);
|
||||
surf->dlightframe = r_dlightframecount;
|
||||
}
|
||||
else // already dynamic
|
||||
surf->dlightbits[num >> 5] |= 1U << (num & 31);
|
||||
}
|
||||
}
|
||||
|
||||
if (node->children[0]->contents >= 0)
|
||||
R_MarkLights (light, num, node->children[0]);
|
||||
if (node->children[1]->contents >= 0)
|
||||
R_MarkLights (light, num, node->children[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_PushDlights
|
||||
=============
|
||||
*/
|
||||
void R_PushDlights (void)
|
||||
{
|
||||
int i;
|
||||
dlight_t *l;
|
||||
|
||||
if (gl_flashblend.value)
|
||||
return;
|
||||
|
||||
r_dlightframecount = r_framecount + 1; // because the count hasn't advanced yet for this frame
|
||||
l = cl_dlights;
|
||||
|
||||
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
|
||||
{
|
||||
if (l->die < cl.time || !l->radius)
|
||||
continue;
|
||||
R_MarkLights (l, i, cl.worldmodel->nodes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
LIGHT SAMPLING
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
//mplane_t *lightplane;
|
||||
vec3_t lightspot;
|
||||
vec3_t lightcolor; //johnfitz -- lit support via lordhavoc
|
||||
|
||||
/*
|
||||
=============
|
||||
RecursiveLightPoint -- johnfitz -- replaced entire function for lit support via lordhavoc
|
||||
=============
|
||||
*/
|
||||
int RecursiveLightPoint (vec3_t color, mnode_t *node, vec3_t rayorg, vec3_t start, vec3_t end, float *maxdist)
|
||||
{
|
||||
float front, back, frac;
|
||||
vec3_t mid;
|
||||
|
||||
loc0:
|
||||
if (node->contents < 0)
|
||||
return false; // didn't hit anything
|
||||
|
||||
// calculate mid point
|
||||
if (node->plane->type < 3)
|
||||
{
|
||||
front = start[node->plane->type] - node->plane->dist;
|
||||
back = end[node->plane->type] - node->plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
front = DotProduct(start, node->plane->normal) - node->plane->dist;
|
||||
back = DotProduct(end, node->plane->normal) - node->plane->dist;
|
||||
}
|
||||
|
||||
// LordHavoc: optimized recursion
|
||||
if ((back < 0) == (front < 0))
|
||||
// return RecursiveLightPoint (color, node->children[front < 0], rayorg, start, end, maxdist);
|
||||
{
|
||||
node = node->children[front < 0];
|
||||
goto loc0;
|
||||
}
|
||||
|
||||
frac = front / (front-back);
|
||||
mid[0] = start[0] + (end[0] - start[0])*frac;
|
||||
mid[1] = start[1] + (end[1] - start[1])*frac;
|
||||
mid[2] = start[2] + (end[2] - start[2])*frac;
|
||||
|
||||
// go down front side
|
||||
if (RecursiveLightPoint (color, node->children[front < 0], rayorg, start, mid, maxdist))
|
||||
return true; // hit something
|
||||
else
|
||||
{
|
||||
int i, ds, dt;
|
||||
msurface_t *surf;
|
||||
// check for impact on this node
|
||||
VectorCopy (mid, lightspot);
|
||||
//lightplane = node->plane;
|
||||
|
||||
surf = cl.worldmodel->surfaces + node->firstsurface;
|
||||
for (i = 0;i < node->numsurfaces;i++, surf++)
|
||||
{
|
||||
float sfront, sback, dist;
|
||||
vec3_t raydelta;
|
||||
|
||||
if (surf->flags & SURF_DRAWTILED)
|
||||
continue; // no lightmaps
|
||||
|
||||
// ericw -- added double casts to force 64-bit precision.
|
||||
// Without them the zombie at the start of jam3_ericw.bsp was
|
||||
// incorrectly being lit up in SSE builds.
|
||||
ds = (int) ((double) DoublePrecisionDotProduct (mid, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]);
|
||||
dt = (int) ((double) DoublePrecisionDotProduct (mid, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]);
|
||||
|
||||
if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
|
||||
continue;
|
||||
|
||||
ds -= surf->texturemins[0];
|
||||
dt -= surf->texturemins[1];
|
||||
|
||||
if (ds > surf->extents[0] || dt > surf->extents[1])
|
||||
continue;
|
||||
|
||||
if (surf->plane->type < 3)
|
||||
{
|
||||
sfront = rayorg[surf->plane->type] - surf->plane->dist;
|
||||
sback = end[surf->plane->type] - surf->plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
sfront = DotProduct(rayorg, surf->plane->normal) - surf->plane->dist;
|
||||
sback = DotProduct(end, surf->plane->normal) - surf->plane->dist;
|
||||
}
|
||||
VectorSubtract(end, rayorg, raydelta);
|
||||
dist = sfront / (sfront - sback) * VectorLength(raydelta);
|
||||
|
||||
if (!surf->samples)
|
||||
{
|
||||
// We hit a surface that is flagged as lightmapped, but doesn't have actual lightmap info.
|
||||
// Instead of just returning black, we'll keep looking for nearby surfaces that do have valid samples.
|
||||
// This fixes occasional pitch-black models in otherwise well-lit areas in DOTM (e.g. mge1m1, mge4m1)
|
||||
// caused by overlapping surfaces with mixed lighting data.
|
||||
const float nearby = 8.f;
|
||||
dist += nearby;
|
||||
*maxdist = q_min(*maxdist, dist);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dist < *maxdist)
|
||||
{
|
||||
// LordHavoc: enhanced to interpolate lighting
|
||||
byte *lightmap;
|
||||
int maps, line3, dsfrac = ds & 15, dtfrac = dt & 15, r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0, r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0;
|
||||
float scale;
|
||||
line3 = ((surf->extents[0]>>4)+1)*3;
|
||||
|
||||
lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color
|
||||
|
||||
for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
|
||||
{
|
||||
scale = (float) d_lightstylevalue[surf->styles[maps]] * 1.0 / 256.0;
|
||||
r00 += (float) lightmap[ 0] * scale;g00 += (float) lightmap[ 1] * scale;b00 += (float) lightmap[2] * scale;
|
||||
r01 += (float) lightmap[ 3] * scale;g01 += (float) lightmap[ 4] * scale;b01 += (float) lightmap[5] * scale;
|
||||
r10 += (float) lightmap[line3+0] * scale;g10 += (float) lightmap[line3+1] * scale;b10 += (float) lightmap[line3+2] * scale;
|
||||
r11 += (float) lightmap[line3+3] * scale;g11 += (float) lightmap[line3+4] * scale;b11 += (float) lightmap[line3+5] * scale;
|
||||
lightmap += ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
|
||||
}
|
||||
|
||||
color[0] += (float) ((int) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)));
|
||||
color[1] += (float) ((int) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)));
|
||||
color[2] += (float) ((int) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)));
|
||||
}
|
||||
return true; // success
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return RecursiveLightPoint (color, node->children[front >= 0], rayorg, mid, end, maxdist);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_LightPoint -- johnfitz -- replaced entire function for lit support via lordhavoc
|
||||
=============
|
||||
*/
|
||||
int R_LightPoint (vec3_t p)
|
||||
{
|
||||
vec3_t end;
|
||||
float maxdist = 8192.f; //johnfitz -- was 2048
|
||||
|
||||
if (!cl.worldmodel->lightdata)
|
||||
{
|
||||
lightcolor[0] = lightcolor[1] = lightcolor[2] = 255;
|
||||
return 255;
|
||||
}
|
||||
|
||||
end[0] = p[0];
|
||||
end[1] = p[1];
|
||||
end[2] = p[2] - maxdist;
|
||||
|
||||
lightcolor[0] = lightcolor[1] = lightcolor[2] = 0;
|
||||
RecursiveLightPoint (lightcolor, cl.worldmodel->nodes, p, p, end, &maxdist);
|
||||
return ((lightcolor[0] + lightcolor[1] + lightcolor[2]) * (1.0f / 3.0f));
|
||||
}
|
||||
+1133
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,645 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2007-2008 Kristian Duske
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// r_misc.c
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
//johnfitz -- new cvars
|
||||
extern cvar_t r_stereo;
|
||||
extern cvar_t r_stereodepth;
|
||||
extern cvar_t r_clearcolor;
|
||||
extern cvar_t r_drawflat;
|
||||
extern cvar_t r_flatlightstyles;
|
||||
extern cvar_t gl_fullbrights;
|
||||
extern cvar_t gl_farclip;
|
||||
extern cvar_t gl_overbright;
|
||||
extern cvar_t gl_overbright_models;
|
||||
extern cvar_t r_waterquality;
|
||||
extern cvar_t r_oldwater;
|
||||
extern cvar_t r_waterwarp;
|
||||
extern cvar_t r_oldskyleaf;
|
||||
extern cvar_t r_drawworld;
|
||||
extern cvar_t r_showtris;
|
||||
extern cvar_t r_showbboxes;
|
||||
extern cvar_t r_lerpmodels;
|
||||
extern cvar_t r_lerpmove;
|
||||
extern cvar_t r_nolerp_list;
|
||||
extern cvar_t r_noshadow_list;
|
||||
//johnfitz
|
||||
extern cvar_t gl_zfix; // QuakeSpasm z-fighting fix
|
||||
|
||||
extern gltexture_t *playertextures[MAX_SCOREBOARD]; //johnfitz
|
||||
|
||||
cvar_t r_lightmapwide = {"r_lightmapwide","0",CVAR_ROM};
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
GL_Overbright_f -- johnfitz
|
||||
====================
|
||||
*/
|
||||
static void GL_Overbright_f (cvar_t *var)
|
||||
{
|
||||
R_RebuildAllLightmaps ();
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
GL_Fullbrights_f -- johnfitz
|
||||
====================
|
||||
*/
|
||||
static void GL_Fullbrights_f (cvar_t *var)
|
||||
{
|
||||
TexMgr_ReloadNobrightImages ();
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_SetClearColor_f -- johnfitz
|
||||
====================
|
||||
*/
|
||||
static void R_SetClearColor_f (cvar_t *var)
|
||||
{
|
||||
byte *rgb;
|
||||
int s;
|
||||
|
||||
s = (int)r_clearcolor.value & 0xFF;
|
||||
rgb = (byte*)(d_8to24table + s);
|
||||
glClearColor (rgb[0]/255.0,rgb[1]/255.0,rgb[2]/255.0,0);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_Model_ExtraFlags_List_f -- johnfitz -- called when r_nolerp_list or r_noshadow_list cvar changes
|
||||
===============
|
||||
*/
|
||||
static void R_Model_ExtraFlags_List_f (cvar_t *var)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < MAX_MODELS; i++)
|
||||
Mod_SetExtraFlags (cl.model_precache[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_SetWateralpha_f -- ericw
|
||||
====================
|
||||
*/
|
||||
static void R_SetWateralpha_f (cvar_t *var)
|
||||
{
|
||||
map_wateralpha = var->value;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_SetLavaalpha_f -- ericw
|
||||
====================
|
||||
*/
|
||||
static void R_SetLavaalpha_f (cvar_t *var)
|
||||
{
|
||||
map_lavaalpha = var->value;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_SetTelealpha_f -- ericw
|
||||
====================
|
||||
*/
|
||||
static void R_SetTelealpha_f (cvar_t *var)
|
||||
{
|
||||
map_telealpha = var->value;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_SetSlimealpha_f -- ericw
|
||||
====================
|
||||
*/
|
||||
static void R_SetSlimealpha_f (cvar_t *var)
|
||||
{
|
||||
map_slimealpha = var->value;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
GL_WaterAlphaForSurfface -- ericw
|
||||
====================
|
||||
*/
|
||||
float GL_WaterAlphaForSurface (msurface_t *fa)
|
||||
{
|
||||
if (fa->flags & SURF_DRAWLAVA)
|
||||
return map_lavaalpha > 0 ? map_lavaalpha : map_wateralpha;
|
||||
else if (fa->flags & SURF_DRAWTELE)
|
||||
return map_telealpha > 0 ? map_telealpha : map_wateralpha;
|
||||
else if (fa->flags & SURF_DRAWSLIME)
|
||||
return map_slimealpha > 0 ? map_slimealpha : map_wateralpha;
|
||||
else
|
||||
return map_wateralpha;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_Init
|
||||
===============
|
||||
*/
|
||||
void R_Init (void)
|
||||
{
|
||||
Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
|
||||
Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
|
||||
|
||||
Cvar_RegisterVariable (&r_norefresh);
|
||||
Cvar_RegisterVariable (&r_lightmap);
|
||||
Cvar_RegisterVariable (&r_fullbright);
|
||||
Cvar_RegisterVariable (&r_drawentities);
|
||||
Cvar_RegisterVariable (&r_drawviewmodel);
|
||||
Cvar_RegisterVariable (&r_shadows);
|
||||
Cvar_RegisterVariable (&r_wateralpha);
|
||||
Cvar_SetCallback (&r_wateralpha, R_SetWateralpha_f);
|
||||
Cvar_RegisterVariable (&r_litwater);
|
||||
Cvar_RegisterVariable (&r_dynamic);
|
||||
Cvar_RegisterVariable (&r_novis);
|
||||
Cvar_RegisterVariable (&r_speeds);
|
||||
Cvar_RegisterVariable (&r_pos);
|
||||
|
||||
Cvar_RegisterVariable (&gl_finish);
|
||||
Cvar_RegisterVariable (&gl_clear);
|
||||
Cvar_RegisterVariable (&gl_cull);
|
||||
Cvar_RegisterVariable (&gl_smoothmodels);
|
||||
Cvar_RegisterVariable (&gl_affinemodels);
|
||||
Cvar_RegisterVariable (&gl_polyblend);
|
||||
Cvar_RegisterVariable (&gl_flashblend);
|
||||
Cvar_RegisterVariable (&gl_playermip);
|
||||
Cvar_RegisterVariable (&gl_nocolors);
|
||||
|
||||
//johnfitz -- new cvars
|
||||
Cvar_RegisterVariable (&r_stereo);
|
||||
Cvar_RegisterVariable (&r_stereodepth);
|
||||
Cvar_RegisterVariable (&r_clearcolor);
|
||||
Cvar_SetCallback (&r_clearcolor, R_SetClearColor_f);
|
||||
Cvar_RegisterVariable (&r_waterquality);
|
||||
Cvar_RegisterVariable (&r_oldwater);
|
||||
Cvar_RegisterVariable (&r_waterwarp);
|
||||
Cvar_RegisterVariable (&r_drawflat);
|
||||
Cvar_RegisterVariable (&r_flatlightstyles);
|
||||
Cvar_RegisterVariable (&r_oldskyleaf);
|
||||
Cvar_RegisterVariable (&r_drawworld);
|
||||
Cvar_RegisterVariable (&r_showtris);
|
||||
Cvar_RegisterVariable (&r_showbboxes);
|
||||
Cvar_RegisterVariable (&gl_farclip);
|
||||
Cvar_RegisterVariable (&gl_fullbrights);
|
||||
Cvar_RegisterVariable (&gl_overbright);
|
||||
Cvar_SetCallback (&gl_fullbrights, GL_Fullbrights_f);
|
||||
Cvar_SetCallback (&gl_overbright, GL_Overbright_f);
|
||||
Cvar_RegisterVariable (&gl_overbright_models);
|
||||
Cvar_RegisterVariable (&r_lerpmodels);
|
||||
Cvar_RegisterVariable (&r_lerpmove);
|
||||
Cvar_RegisterVariable (&r_nolerp_list);
|
||||
Cvar_SetCallback (&r_nolerp_list, R_Model_ExtraFlags_List_f);
|
||||
Cvar_RegisterVariable (&r_noshadow_list);
|
||||
Cvar_SetCallback (&r_noshadow_list, R_Model_ExtraFlags_List_f);
|
||||
//johnfitz
|
||||
Cvar_RegisterVariable (&r_lightmapwide);
|
||||
Cvar_SetROM ("r_lightmapwide", gl_packed_pixels ? "1" : "0");
|
||||
|
||||
Cvar_RegisterVariable (&gl_zfix); // QuakeSpasm z-fighting fix
|
||||
Cvar_RegisterVariable (&r_lavaalpha);
|
||||
Cvar_RegisterVariable (&r_telealpha);
|
||||
Cvar_RegisterVariable (&r_slimealpha);
|
||||
Cvar_RegisterVariable (&r_scale);
|
||||
Cvar_SetCallback (&r_lavaalpha, R_SetLavaalpha_f);
|
||||
Cvar_SetCallback (&r_telealpha, R_SetTelealpha_f);
|
||||
Cvar_SetCallback (&r_slimealpha, R_SetSlimealpha_f);
|
||||
|
||||
R_InitParticles ();
|
||||
R_SetClearColor_f (&r_clearcolor); //johnfitz
|
||||
|
||||
Sky_Init (); //johnfitz
|
||||
Fog_Init (); //johnfitz
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_TranslatePlayerSkin -- johnfitz -- rewritten. also, only handles new colors, not new skins
|
||||
===============
|
||||
*/
|
||||
void R_TranslatePlayerSkin (int playernum)
|
||||
{
|
||||
int top, bottom;
|
||||
|
||||
top = (cl.scores[playernum].colors & 0xf0)>>4;
|
||||
bottom = cl.scores[playernum].colors &15;
|
||||
|
||||
//FIXME: if gl_nocolors is on, then turned off, the textures may be out of sync with the scoreboard colors.
|
||||
if (!gl_nocolors.value)
|
||||
{
|
||||
if (playertextures[playernum])
|
||||
TexMgr_ReloadImage (playertextures[playernum], top, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_TranslateNewPlayerSkin -- johnfitz -- split off of TranslatePlayerSkin -- this is called when
|
||||
the skin or model actually changes, instead of just new colors
|
||||
added bug fix from bengt jardup
|
||||
===============
|
||||
*/
|
||||
void R_TranslateNewPlayerSkin (int playernum)
|
||||
{
|
||||
char name[64];
|
||||
byte *pixels;
|
||||
aliashdr_t *paliashdr;
|
||||
int skinnum;
|
||||
|
||||
//get correct texture pixels
|
||||
currententity = &cl_entities[1+playernum];
|
||||
|
||||
if (!currententity->model || currententity->model->type != mod_alias)
|
||||
return;
|
||||
|
||||
paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
|
||||
|
||||
skinnum = currententity->skinnum;
|
||||
|
||||
//TODO: move these tests to the place where skinnum gets received from the server
|
||||
if (skinnum < 0 || skinnum >= paliashdr->numskins)
|
||||
{
|
||||
Con_DPrintf("(%d): Invalid player skin #%d\n", playernum, skinnum);
|
||||
skinnum = 0;
|
||||
}
|
||||
|
||||
pixels = (byte *)paliashdr + paliashdr->texels[skinnum]; // This is not a persistent place!
|
||||
|
||||
//upload new image
|
||||
q_snprintf(name, sizeof(name), "player_%i", playernum);
|
||||
playertextures[playernum] = TexMgr_LoadImage (currententity->model, name, paliashdr->skinwidth, paliashdr->skinheight,
|
||||
SRC_INDEXED, pixels, paliashdr->gltextures[skinnum][0]->source_file, paliashdr->gltextures[skinnum][0]->source_offset, TEXPREF_PAD | TEXPREF_OVERWRITE);
|
||||
|
||||
//now recolor it
|
||||
R_TranslatePlayerSkin (playernum);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_NewGame -- johnfitz -- handle a game switch
|
||||
===============
|
||||
*/
|
||||
void R_NewGame (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
//clear playertexture pointers (the textures themselves were freed by texmgr_newgame)
|
||||
for (i=0; i<MAX_SCOREBOARD; i++)
|
||||
playertextures[i] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_ParseWorldspawn
|
||||
|
||||
called at map load
|
||||
=============
|
||||
*/
|
||||
static void R_ParseWorldspawn (void)
|
||||
{
|
||||
char key[128], value[4096];
|
||||
const char *data;
|
||||
|
||||
map_wateralpha = r_wateralpha.value;
|
||||
map_lavaalpha = r_lavaalpha.value;
|
||||
map_telealpha = r_telealpha.value;
|
||||
map_slimealpha = r_slimealpha.value;
|
||||
|
||||
data = COM_Parse(cl.worldmodel->entities);
|
||||
if (!data)
|
||||
return; // error
|
||||
if (com_token[0] != '{')
|
||||
return; // error
|
||||
|
||||
while (1)
|
||||
{
|
||||
data = COM_Parse(data);
|
||||
if (!data)
|
||||
return; // error
|
||||
if (com_token[0] == '}')
|
||||
break; // end of worldspawn
|
||||
if (com_token[0] == '_')
|
||||
q_strlcpy(key, com_token + 1, sizeof(key));
|
||||
else
|
||||
q_strlcpy(key, com_token, sizeof(key));
|
||||
while (key[0] && key[strlen(key)-1] == ' ') // remove trailing spaces
|
||||
key[strlen(key)-1] = 0;
|
||||
data = COM_ParseEx(data, CPE_ALLOWTRUNC);
|
||||
if (!data)
|
||||
return; // error
|
||||
q_strlcpy(value, com_token, sizeof(value));
|
||||
|
||||
if (!strcmp("wateralpha", key))
|
||||
map_wateralpha = atof(value);
|
||||
|
||||
if (!strcmp("lavaalpha", key))
|
||||
map_lavaalpha = atof(value);
|
||||
|
||||
if (!strcmp("telealpha", key))
|
||||
map_telealpha = atof(value);
|
||||
|
||||
if (!strcmp("slimealpha", key))
|
||||
map_slimealpha = atof(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
R_NewMap
|
||||
===============
|
||||
*/
|
||||
void R_NewMap (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<256 ; i++)
|
||||
d_lightstylevalue[i] = 264; // normal light value
|
||||
|
||||
// clear out efrags in case the level hasn't been reloaded
|
||||
// FIXME: is this one short?
|
||||
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
|
||||
cl.worldmodel->leafs[i].efrags = NULL;
|
||||
|
||||
r_viewleaf = NULL;
|
||||
R_ClearParticles ();
|
||||
|
||||
GL_BuildLightmaps ();
|
||||
GL_BuildBModelVertexBuffer ();
|
||||
//ericw -- no longer load alias models into a VBO here, it's done in Mod_LoadAliasModel
|
||||
|
||||
r_framecount = 0; //johnfitz -- paranoid?
|
||||
r_visframecount = 0; //johnfitz -- paranoid?
|
||||
|
||||
Sky_NewMap (); //johnfitz -- skybox in worldspawn
|
||||
Fog_NewMap (); //johnfitz -- global fog in worldspawn
|
||||
R_ParseWorldspawn (); //ericw -- wateralpha, lavaalpha, telealpha, slimealpha in worldspawn
|
||||
|
||||
load_subdivide_size = gl_subdivide_size.value; //johnfitz -- is this the right place to set this?
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_TimeRefresh_f
|
||||
|
||||
For program optimization
|
||||
====================
|
||||
*/
|
||||
void R_TimeRefresh_f (void)
|
||||
{
|
||||
int i;
|
||||
float start, stop, time;
|
||||
|
||||
if (cls.state != ca_connected)
|
||||
{
|
||||
Con_Printf("Not connected to a server\n");
|
||||
return;
|
||||
}
|
||||
|
||||
start = Sys_DoubleTime ();
|
||||
for (i = 0; i < 128; i++)
|
||||
{
|
||||
GL_BeginRendering(&glx, &gly, &glwidth, &glheight);
|
||||
r_refdef.viewangles[1] = i/128.0*360.0;
|
||||
R_RenderView ();
|
||||
GL_EndRendering ();
|
||||
}
|
||||
|
||||
glFinish ();
|
||||
stop = Sys_DoubleTime ();
|
||||
time = stop-start;
|
||||
Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
|
||||
}
|
||||
|
||||
void D_FlushCaches (void)
|
||||
{
|
||||
}
|
||||
|
||||
static GLuint gl_programs[16];
|
||||
static int gl_num_programs;
|
||||
|
||||
static qboolean GL_CheckShader (GLuint shader)
|
||||
{
|
||||
GLint status;
|
||||
GL_GetShaderivFunc (shader, GL_COMPILE_STATUS, &status);
|
||||
|
||||
if (status != GL_TRUE)
|
||||
{
|
||||
char infolog[1024];
|
||||
|
||||
memset(infolog, 0, sizeof(infolog));
|
||||
GL_GetShaderInfoLogFunc (shader, sizeof(infolog), NULL, infolog);
|
||||
|
||||
Con_Warning ("GLSL program failed to compile: %s", infolog);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean GL_CheckProgram (GLuint program)
|
||||
{
|
||||
GLint status;
|
||||
GL_GetProgramivFunc (program, GL_LINK_STATUS, &status);
|
||||
|
||||
if (status != GL_TRUE)
|
||||
{
|
||||
char infolog[1024];
|
||||
|
||||
memset(infolog, 0, sizeof(infolog));
|
||||
GL_GetProgramInfoLogFunc (program, sizeof(infolog), NULL, infolog);
|
||||
|
||||
Con_Warning ("GLSL program failed to link: %s", infolog);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
GL_GetUniformLocation
|
||||
=============
|
||||
*/
|
||||
GLint GL_GetUniformLocation (GLuint *programPtr, const char *name)
|
||||
{
|
||||
GLint location;
|
||||
|
||||
if (!programPtr)
|
||||
return -1;
|
||||
|
||||
location = GL_GetUniformLocationFunc(*programPtr, name);
|
||||
if (location == -1)
|
||||
{
|
||||
Con_Warning("GL_GetUniformLocationFunc %s failed\n", name);
|
||||
*programPtr = 0;
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
GL_CreateProgram
|
||||
|
||||
Compiles and returns GLSL program.
|
||||
====================
|
||||
*/
|
||||
GLuint GL_CreateProgram (const GLchar *vertSource, const GLchar *fragSource, int numbindings, const glsl_attrib_binding_t *bindings)
|
||||
{
|
||||
int i;
|
||||
GLuint program, vertShader, fragShader;
|
||||
|
||||
if (!gl_glsl_able)
|
||||
return 0;
|
||||
|
||||
vertShader = GL_CreateShaderFunc (GL_VERTEX_SHADER);
|
||||
GL_ShaderSourceFunc (vertShader, 1, &vertSource, NULL);
|
||||
GL_CompileShaderFunc (vertShader);
|
||||
if (!GL_CheckShader (vertShader))
|
||||
{
|
||||
GL_DeleteShaderFunc (vertShader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fragShader = GL_CreateShaderFunc (GL_FRAGMENT_SHADER);
|
||||
GL_ShaderSourceFunc (fragShader, 1, &fragSource, NULL);
|
||||
GL_CompileShaderFunc (fragShader);
|
||||
if (!GL_CheckShader (fragShader))
|
||||
{
|
||||
GL_DeleteShaderFunc (vertShader);
|
||||
GL_DeleteShaderFunc (fragShader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
program = GL_CreateProgramFunc ();
|
||||
GL_AttachShaderFunc (program, vertShader);
|
||||
GL_DeleteShaderFunc (vertShader);
|
||||
GL_AttachShaderFunc (program, fragShader);
|
||||
GL_DeleteShaderFunc (fragShader);
|
||||
|
||||
for (i = 0; i < numbindings; i++)
|
||||
{
|
||||
GL_BindAttribLocationFunc (program, bindings[i].attrib, bindings[i].name);
|
||||
}
|
||||
|
||||
GL_LinkProgramFunc (program);
|
||||
|
||||
if (!GL_CheckProgram (program))
|
||||
{
|
||||
GL_DeleteProgramFunc (program);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gl_num_programs == Q_COUNTOF(gl_programs))
|
||||
Host_Error ("gl_programs overflow");
|
||||
|
||||
gl_programs[gl_num_programs] = program;
|
||||
gl_num_programs++;
|
||||
|
||||
return program;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
R_DeleteShaders
|
||||
|
||||
Deletes any GLSL programs that have been created.
|
||||
====================
|
||||
*/
|
||||
void R_DeleteShaders (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!gl_glsl_able)
|
||||
return;
|
||||
|
||||
for (i = 0; i < gl_num_programs; i++)
|
||||
{
|
||||
GL_DeleteProgramFunc (gl_programs[i]);
|
||||
gl_programs[i] = 0;
|
||||
}
|
||||
gl_num_programs = 0;
|
||||
}
|
||||
|
||||
static GLuint current_array_buffer, current_element_array_buffer;
|
||||
|
||||
/*
|
||||
====================
|
||||
GL_BindBuffer
|
||||
|
||||
glBindBuffer wrapper
|
||||
====================
|
||||
*/
|
||||
void GL_BindBuffer (GLenum target, GLuint buffer)
|
||||
{
|
||||
GLuint *cache;
|
||||
|
||||
if (!gl_vbo_able)
|
||||
return;
|
||||
|
||||
switch (target)
|
||||
{
|
||||
case GL_ARRAY_BUFFER:
|
||||
cache = ¤t_array_buffer;
|
||||
break;
|
||||
case GL_ELEMENT_ARRAY_BUFFER:
|
||||
cache = ¤t_element_array_buffer;
|
||||
break;
|
||||
default:
|
||||
Host_Error("GL_BindBuffer: unsupported target %d", (int)target);
|
||||
return;
|
||||
}
|
||||
|
||||
if (*cache != buffer)
|
||||
{
|
||||
*cache = buffer;
|
||||
GL_BindBufferFunc (target, *cache);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
GL_ClearBufferBindings
|
||||
|
||||
This must be called if you do anything that could make the cached bindings
|
||||
invalid (e.g. manually binding, destroying the context).
|
||||
====================
|
||||
*/
|
||||
void GL_ClearBufferBindings (void)
|
||||
{
|
||||
if (!gl_vbo_able)
|
||||
return;
|
||||
|
||||
current_array_buffer = 0;
|
||||
current_element_array_buffer = 0;
|
||||
GL_BindBufferFunc (GL_ARRAY_BUFFER, 0);
|
||||
GL_BindBufferFunc (GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
+1116
File diff suppressed because it is too large
Load Diff
+1134
File diff suppressed because it is too large
Load Diff
+1551
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 _GL_TEXMAN_H
|
||||
#define _GL_TEXMAN_H
|
||||
|
||||
//gl_texmgr.h -- fitzquake's texture manager. manages opengl texture images
|
||||
|
||||
#define TEXPREF_NONE 0x0000
|
||||
#define TEXPREF_MIPMAP 0x0001 // generate mipmaps
|
||||
// TEXPREF_NEAREST and TEXPREF_LINEAR aren't supposed to be ORed with TEX_MIPMAP
|
||||
#define TEXPREF_LINEAR 0x0002 // force linear
|
||||
#define TEXPREF_NEAREST 0x0004 // force nearest
|
||||
#define TEXPREF_ALPHA 0x0008 // allow alpha
|
||||
#define TEXPREF_PAD 0x0010 // allow padding
|
||||
#define TEXPREF_PERSIST 0x0020 // never free
|
||||
#define TEXPREF_OVERWRITE 0x0040 // overwrite existing same-name texture
|
||||
#define TEXPREF_NOPICMIP 0x0080 // always load full-sized
|
||||
#define TEXPREF_FULLBRIGHT 0x0100 // use fullbright mask palette
|
||||
#define TEXPREF_NOBRIGHT 0x0200 // use nobright mask palette
|
||||
#define TEXPREF_CONCHARS 0x0400 // use conchars palette
|
||||
#define TEXPREF_WARPIMAGE 0x0800 // resize this texture when warpimagesize changes
|
||||
|
||||
enum srcformat {SRC_INDEXED, SRC_LIGHTMAP, SRC_RGBA};
|
||||
|
||||
typedef uintptr_t src_offset_t;
|
||||
|
||||
typedef struct gltexture_s {
|
||||
//managed by texture manager
|
||||
GLuint texnum;
|
||||
struct gltexture_s *next;
|
||||
qmodel_t *owner;
|
||||
//managed by image loading
|
||||
char name[64];
|
||||
unsigned int width; //size of image as it exists in opengl
|
||||
unsigned int height; //size of image as it exists in opengl
|
||||
unsigned int flags;
|
||||
char source_file[MAX_QPATH]; //relative filepath to data source, or "" if source is in memory
|
||||
src_offset_t source_offset; //byte offset into file, or memory address
|
||||
enum srcformat source_format; //format of pixel data (indexed, lightmap, or rgba)
|
||||
unsigned int source_width; //size of image in source data
|
||||
unsigned int source_height; //size of image in source data
|
||||
unsigned short source_crc; //generated by source data before modifications
|
||||
signed char shirt; //0-13 shirt color, or -1 if never colormapped
|
||||
signed char pants; //0-13 pants color, or -1 if never colormapped
|
||||
//used for rendering
|
||||
int visframe; //matches r_framecount if texture was bound this frame
|
||||
} gltexture_t;
|
||||
|
||||
extern gltexture_t *notexture;
|
||||
extern gltexture_t *nulltexture;
|
||||
|
||||
extern unsigned int d_8to24table[256];
|
||||
extern unsigned int d_8to24table_fbright[256];
|
||||
extern unsigned int d_8to24table_nobright[256];
|
||||
extern unsigned int d_8to24table_conchars[256];
|
||||
|
||||
// TEXTURE MANAGER
|
||||
|
||||
float TexMgr_FrameUsage (void);
|
||||
gltexture_t *TexMgr_FindTexture (qmodel_t *owner, const char *name);
|
||||
gltexture_t *TexMgr_NewTexture (void);
|
||||
void TexMgr_FreeTexture (gltexture_t *kill);
|
||||
void TexMgr_FreeTextures (unsigned int flags, unsigned int mask);
|
||||
void TexMgr_FreeTexturesForOwner (qmodel_t *owner);
|
||||
void TexMgr_NewGame (void);
|
||||
void TexMgr_Init (void);
|
||||
void TexMgr_DeleteTextureObjects (void);
|
||||
|
||||
// IMAGE LOADING
|
||||
gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int height, enum srcformat format,
|
||||
byte *data, const char *source_file, src_offset_t source_offset, unsigned flags);
|
||||
void TexMgr_ReloadImage (gltexture_t *glt, int shirt, int pants);
|
||||
void TexMgr_ReloadImages (void);
|
||||
void TexMgr_ReloadNobrightImages (void);
|
||||
|
||||
int TexMgr_Pad(int s);
|
||||
int TexMgr_SafeTextureSize (int s);
|
||||
int TexMgr_PadConditional (int s);
|
||||
|
||||
// TEXTURE BINDING & TEXTURE UNIT SWITCHING
|
||||
|
||||
void GL_SelectTexture (GLenum target);
|
||||
void GL_DisableMultitexture (void); //selects texture unit 0
|
||||
void GL_EnableMultitexture (void); //selects texture unit 1
|
||||
void GL_Bind (gltexture_t *texture);
|
||||
void GL_ClearBindings (void);
|
||||
|
||||
#endif /* _GL_TEXMAN_H */
|
||||
|
||||
+2392
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
*/
|
||||
//gl_warp.c -- warping animation support
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
extern cvar_t r_drawflat;
|
||||
|
||||
cvar_t r_oldwater = {"r_oldwater", "0", CVAR_ARCHIVE};
|
||||
cvar_t r_waterquality = {"r_waterquality", "8", CVAR_NONE};
|
||||
cvar_t r_waterwarp = {"r_waterwarp", "1", CVAR_NONE};
|
||||
|
||||
int gl_warpimagesize;
|
||||
float load_subdivide_size; //johnfitz -- remember what subdivide_size value was when this map was loaded
|
||||
|
||||
static const float turbsin[] = {
|
||||
#include "gl_warp_sin.hpp"
|
||||
};
|
||||
|
||||
#define WARPCALC(s,t) ((s + turbsin[(int)((t*2)+(cl.time*(128.0/M_PI))) & 255]) * (1.0/64)) //johnfitz -- correct warp
|
||||
#define WARPCALC2(s,t) ((s + turbsin[(int)((t*0.125+cl.time)*(128.0/M_PI)) & 255]) * (1.0/64)) //johnfitz -- old warp
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// OLD-STYLE WATER
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
static msurface_t *warpface;
|
||||
|
||||
cvar_t gl_subdivide_size = {"gl_subdivide_size", "128", CVAR_ARCHIVE};
|
||||
|
||||
static void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
int i, j;
|
||||
float *v;
|
||||
|
||||
mins[0] = mins[1] = mins[2] = FLT_MAX;
|
||||
maxs[0] = maxs[1] = maxs[2] = -FLT_MAX;
|
||||
v = verts;
|
||||
for (i=0 ; i<numverts ; i++)
|
||||
for (j=0 ; j<3 ; j++, v++)
|
||||
{
|
||||
if (*v < mins[j])
|
||||
mins[j] = *v;
|
||||
if (*v > maxs[j])
|
||||
maxs[j] = *v;
|
||||
}
|
||||
}
|
||||
|
||||
static void SubdividePolygon (int numverts, float *verts)
|
||||
{
|
||||
int i, j, k;
|
||||
vec3_t mins, maxs;
|
||||
float m;
|
||||
float *v;
|
||||
vec3_t front[64], back[64];
|
||||
int f, b;
|
||||
float dist[64];
|
||||
float frac;
|
||||
glpoly_t *poly;
|
||||
float s, t;
|
||||
|
||||
if (numverts > 60)
|
||||
Sys_Error ("SubdividePolygon: numverts = %i", numverts);
|
||||
|
||||
BoundPoly (numverts, verts, mins, maxs);
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
m = (mins[i] + maxs[i]) * 0.5;
|
||||
m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5);
|
||||
if (maxs[i] - m < 8)
|
||||
continue;
|
||||
if (m - mins[i] < 8)
|
||||
continue;
|
||||
|
||||
// cut it
|
||||
v = verts + i;
|
||||
for (j=0 ; j<numverts ; j++, v+= 3)
|
||||
dist[j] = *v - m;
|
||||
|
||||
// wrap cases
|
||||
dist[j] = dist[0];
|
||||
v-=i;
|
||||
VectorCopy (verts, v);
|
||||
|
||||
f = b = 0;
|
||||
v = verts;
|
||||
for (j=0 ; j<numverts ; j++, v+= 3)
|
||||
{
|
||||
if (dist[j] >= 0)
|
||||
{
|
||||
VectorCopy (v, front[f]);
|
||||
f++;
|
||||
}
|
||||
if (dist[j] <= 0)
|
||||
{
|
||||
VectorCopy (v, back[b]);
|
||||
b++;
|
||||
}
|
||||
if (dist[j] == 0 || dist[j+1] == 0)
|
||||
continue;
|
||||
if ( (dist[j] > 0) != (dist[j+1] > 0) )
|
||||
{
|
||||
// clip point
|
||||
frac = dist[j] / (dist[j] - dist[j+1]);
|
||||
for (k=0 ; k<3 ; k++)
|
||||
front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]);
|
||||
f++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
SubdividePolygon (f, front[0]);
|
||||
SubdividePolygon (b, back[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
poly = (glpoly_t *) Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float));
|
||||
poly->next = warpface->polys->next;
|
||||
warpface->polys->next = poly;
|
||||
poly->numverts = numverts;
|
||||
for (i=0 ; i<numverts ; i++, verts+= 3)
|
||||
{
|
||||
VectorCopy (verts, poly->verts[i]);
|
||||
s = DotProduct (verts, warpface->texinfo->vecs[0]);
|
||||
t = DotProduct (verts, warpface->texinfo->vecs[1]);
|
||||
poly->verts[i][3] = s;
|
||||
poly->verts[i][4] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GL_SubdivideSurface
|
||||
================
|
||||
*/
|
||||
void GL_SubdivideSurface (msurface_t *fa)
|
||||
{
|
||||
vec3_t verts[64];
|
||||
int i;
|
||||
|
||||
if (fa->polys->numverts > 64)
|
||||
Sys_Error ("GL_SubdivideSurface: numverts = %i", fa->polys->numverts);
|
||||
|
||||
warpface = fa;
|
||||
|
||||
//the first poly in the chain is the undivided poly for newwater rendering.
|
||||
//grab the verts from that.
|
||||
for (i=0; i<fa->polys->numverts; i++)
|
||||
VectorCopy (fa->polys->verts[i], verts[i]);
|
||||
|
||||
SubdividePolygon (fa->polys->numverts, verts[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
DrawWaterPoly -- johnfitz
|
||||
================
|
||||
*/
|
||||
void DrawWaterPoly (glpoly_t *p)
|
||||
{
|
||||
float *v;
|
||||
int i;
|
||||
|
||||
if (load_subdivide_size > 48)
|
||||
{
|
||||
glBegin (GL_POLYGON);
|
||||
v = p->verts[0];
|
||||
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
|
||||
{
|
||||
glTexCoord2f (WARPCALC2(v[3],v[4]), WARPCALC2(v[4],v[3]));
|
||||
glVertex3fv (v);
|
||||
}
|
||||
glEnd ();
|
||||
}
|
||||
else
|
||||
{
|
||||
glBegin (GL_POLYGON);
|
||||
v = p->verts[0];
|
||||
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
|
||||
{
|
||||
glTexCoord2f (WARPCALC(v[3],v[4]), WARPCALC(v[4],v[3]));
|
||||
glVertex3fv (v);
|
||||
}
|
||||
glEnd ();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// RENDER-TO-FRAMEBUFFER WATER
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
R_UpdateWarpTextures -- johnfitz -- each frame, update warping textures
|
||||
=============
|
||||
*/
|
||||
#ifdef __WATCOMC__ /* OW1.9 doesn't have floorf() */
|
||||
#define floorf(_val) (float)floor((_val))
|
||||
#endif
|
||||
void R_UpdateWarpTextures (void)
|
||||
{
|
||||
texture_t *tx;
|
||||
int i;
|
||||
float x, y, x2, warptess;
|
||||
|
||||
if (r_oldwater.value || cl.paused || r_drawflat_cheatsafe || r_lightmap_cheatsafe)
|
||||
return;
|
||||
|
||||
warptess = 128.0f/CLAMP (3.0f, floorf(r_waterquality.value), 64.0f);
|
||||
|
||||
for (i=0; i<cl.worldmodel->numtextures; i++)
|
||||
{
|
||||
if (!(tx = cl.worldmodel->textures[i]))
|
||||
continue;
|
||||
|
||||
if (!tx->update_warp)
|
||||
continue;
|
||||
|
||||
//render warp
|
||||
GL_SetCanvas (CANVAS_WARPIMAGE);
|
||||
GL_Bind (tx->gltexture);
|
||||
for (x=0.0; x<128.0; x=x2)
|
||||
{
|
||||
x2 = x + warptess;
|
||||
glBegin (GL_TRIANGLE_STRIP);
|
||||
for (y=0.0; y<128.01; y+=warptess) // .01 for rounding errors
|
||||
{
|
||||
glTexCoord2f (WARPCALC(x,y), WARPCALC(y,x));
|
||||
glVertex2f (x,y);
|
||||
glTexCoord2f (WARPCALC(x2,y), WARPCALC(y,x2));
|
||||
glVertex2f (x2,y);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
//copy to texture
|
||||
GL_Bind (tx->warpimage);
|
||||
glCopyTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, glx, gly+glheight-gl_warpimagesize, gl_warpimagesize, gl_warpimagesize);
|
||||
if (GL_GenerateMipmap)
|
||||
GL_GenerateMipmap (GL_TEXTURE_2D);
|
||||
|
||||
tx->update_warp = false;
|
||||
}
|
||||
|
||||
// ericw -- workaround for osx 10.6 driver bug when using FSAA. R_Clear only clears the warpimage part of the screen.
|
||||
GL_SetCanvas(CANVAS_DEFAULT);
|
||||
|
||||
//if warp render went down into sbar territory, we need to be sure to refresh it next frame
|
||||
if (gl_warpimagesize + sb_lines > glheight)
|
||||
Sbar_Changed ();
|
||||
|
||||
//if viewsize is less than 100, we need to redraw the frame around the viewport
|
||||
scr_tileclear_updates = 0;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* gl_warp_sin.h
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
0, 0.19633, 0.392541, 0.588517,
|
||||
0.784137, 0.979285, 1.17384, 1.3677,
|
||||
1.56072, 1.75281, 1.94384, 2.1337,
|
||||
2.32228, 2.50945, 2.69512, 2.87916,
|
||||
3.06147, 3.24193, 3.42044, 3.59689,
|
||||
3.77117, 3.94319, 4.11282, 4.27998,
|
||||
4.44456, 4.60647, 4.76559, 4.92185,
|
||||
5.07515, 5.22538, 5.37247, 5.51632,
|
||||
5.65685, 5.79398, 5.92761, 6.05767,
|
||||
6.18408, 6.30677, 6.42566, 6.54068,
|
||||
6.65176, 6.75883, 6.86183, 6.9607,
|
||||
7.05537, 7.14579, 7.23191, 7.31368,
|
||||
7.39104, 7.46394, 7.53235, 7.59623,
|
||||
7.65552, 7.71021, 7.76025, 7.80562,
|
||||
7.84628, 7.88222, 7.91341, 7.93984,
|
||||
7.96148, 7.97832, 7.99036, 7.99759,
|
||||
8, 7.99759, 7.99036, 7.97832,
|
||||
7.96148, 7.93984, 7.91341, 7.88222,
|
||||
7.84628, 7.80562, 7.76025, 7.71021,
|
||||
7.65552, 7.59623, 7.53235, 7.46394,
|
||||
7.39104, 7.31368, 7.23191, 7.14579,
|
||||
7.05537, 6.9607, 6.86183, 6.75883,
|
||||
6.65176, 6.54068, 6.42566, 6.30677,
|
||||
6.18408, 6.05767, 5.92761, 5.79398,
|
||||
5.65685, 5.51632, 5.37247, 5.22538,
|
||||
5.07515, 4.92185, 4.76559, 4.60647,
|
||||
4.44456, 4.27998, 4.11282, 3.94319,
|
||||
3.77117, 3.59689, 3.42044, 3.24193,
|
||||
3.06147, 2.87916, 2.69512, 2.50945,
|
||||
2.32228, 2.1337, 1.94384, 1.75281,
|
||||
1.56072, 1.3677, 1.17384, 0.979285,
|
||||
0.784137, 0.588517, 0.392541, 0.19633,
|
||||
9.79717e-16, -0.19633, -0.392541, -0.588517,
|
||||
-0.784137, -0.979285, -1.17384, -1.3677,
|
||||
-1.56072, -1.75281, -1.94384, -2.1337,
|
||||
-2.32228, -2.50945, -2.69512, -2.87916,
|
||||
-3.06147, -3.24193, -3.42044, -3.59689,
|
||||
-3.77117, -3.94319, -4.11282, -4.27998,
|
||||
-4.44456, -4.60647, -4.76559, -4.92185,
|
||||
-5.07515, -5.22538, -5.37247, -5.51632,
|
||||
-5.65685, -5.79398, -5.92761, -6.05767,
|
||||
-6.18408, -6.30677, -6.42566, -6.54068,
|
||||
-6.65176, -6.75883, -6.86183, -6.9607,
|
||||
-7.05537, -7.14579, -7.23191, -7.31368,
|
||||
-7.39104, -7.46394, -7.53235, -7.59623,
|
||||
-7.65552, -7.71021, -7.76025, -7.80562,
|
||||
-7.84628, -7.88222, -7.91341, -7.93984,
|
||||
-7.96148, -7.97832, -7.99036, -7.99759,
|
||||
-8, -7.99759, -7.99036, -7.97832,
|
||||
-7.96148, -7.93984, -7.91341, -7.88222,
|
||||
-7.84628, -7.80562, -7.76025, -7.71021,
|
||||
-7.65552, -7.59623, -7.53235, -7.46394,
|
||||
-7.39104, -7.31368, -7.23191, -7.14579,
|
||||
-7.05537, -6.9607, -6.86183, -6.75883,
|
||||
-6.65176, -6.54068, -6.42566, -6.30677,
|
||||
-6.18408, -6.05767, -5.92761, -5.79398,
|
||||
-5.65685, -5.51632, -5.37247, -5.22538,
|
||||
-5.07515, -4.92185, -4.76559, -4.60647,
|
||||
-4.44456, -4.27998, -4.11282, -3.94319,
|
||||
-3.77117, -3.59689, -3.42044, -3.24193,
|
||||
-3.06147, -2.87916, -2.69512, -2.50945,
|
||||
-2.32228, -2.1337, -1.94384, -1.75281,
|
||||
-1.56072, -1.3677, -1.17384, -0.979285,
|
||||
-0.784137, -0.588517, -0.392541, -0.19633,
|
||||
|
||||
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2007-2008 Kristian Duske
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 GLQUAKE_H
|
||||
#define GLQUAKE_H
|
||||
|
||||
void GL_BeginRendering (int *x, int *y, int *width, int *height);
|
||||
void GL_EndRendering (void);
|
||||
void GL_Set2D (void);
|
||||
|
||||
extern int glx, gly, glwidth, glheight;
|
||||
|
||||
#define GL_UNUSED_TEXTURE (~(GLuint)0)
|
||||
|
||||
// r_local.h -- private refresh defs
|
||||
|
||||
#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0)
|
||||
// normalizing factor so player model works out to about
|
||||
// 1 pixel per triangle
|
||||
#define MAX_LBM_HEIGHT 480
|
||||
|
||||
#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf
|
||||
|
||||
#define SKYSHIFT 7
|
||||
#define SKYSIZE (1 << SKYSHIFT)
|
||||
#define SKYMASK (SKYSIZE - 1)
|
||||
|
||||
#define BACKFACE_EPSILON 0.01
|
||||
|
||||
|
||||
void R_TimeRefresh_f (void);
|
||||
void R_ReadPointFile_f (void);
|
||||
texture_t *R_TextureAnimation (texture_t *base, int frame);
|
||||
|
||||
typedef struct surfcache_s
|
||||
{
|
||||
struct surfcache_s *next;
|
||||
struct surfcache_s **owner; // NULL is an empty chunk of memory
|
||||
int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
|
||||
int dlight;
|
||||
int size; // including header
|
||||
unsigned width;
|
||||
unsigned height; // DEBUG only needed for debug
|
||||
float mipscale;
|
||||
struct texture_s *texture; // checked for animating textures
|
||||
byte data[4]; // width*height elements
|
||||
} surfcache_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pixel_t *surfdat; // destination for generated surface
|
||||
int rowbytes; // destination logical width in bytes
|
||||
msurface_t *surf; // description for surface to generate
|
||||
fixed8_t lightadj[MAXLIGHTMAPS];
|
||||
// adjust for lightmap levels for dynamic lighting
|
||||
texture_t *texture; // corrected for animating textures
|
||||
int surfmip; // mipmapped ratio of surface texels / world pixels
|
||||
int surfwidth; // in mipmapped texels
|
||||
int surfheight; // in mipmapped texels
|
||||
} drawsurf_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
pt_static, pt_grav, pt_slowgrav, pt_fire, pt_explode, pt_explode2, pt_blob, pt_blob2
|
||||
} ptype_t;
|
||||
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
typedef struct particle_s
|
||||
{
|
||||
// driver-usable fields
|
||||
vec3_t org;
|
||||
float color;
|
||||
// drivers never touch the following fields
|
||||
struct particle_s *next;
|
||||
vec3_t vel;
|
||||
float ramp;
|
||||
float die;
|
||||
ptype_t type;
|
||||
} particle_t;
|
||||
|
||||
|
||||
//====================================================
|
||||
|
||||
extern vec3_t modelorg, r_entorigin;
|
||||
extern entity_t *currententity;
|
||||
extern int r_visframecount; // ??? what difs?
|
||||
extern int r_framecount;
|
||||
extern mplane_t frustum[4];
|
||||
|
||||
extern texture_t *r_notexture_mip, *r_notexture_mip2;
|
||||
|
||||
//
|
||||
// view origin
|
||||
//
|
||||
extern vec3_t vup;
|
||||
extern vec3_t vpn;
|
||||
extern vec3_t vright;
|
||||
extern vec3_t r_origin;
|
||||
|
||||
//
|
||||
// screen size info
|
||||
//
|
||||
extern refdef_t r_refdef;
|
||||
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
|
||||
extern int d_lightstylevalue[256]; // 8.8 fraction of base light value
|
||||
|
||||
extern cvar_t r_norefresh;
|
||||
extern cvar_t r_drawentities;
|
||||
extern cvar_t r_drawworld;
|
||||
extern cvar_t r_drawviewmodel;
|
||||
extern cvar_t r_speeds;
|
||||
extern cvar_t r_pos;
|
||||
extern cvar_t r_waterwarp;
|
||||
extern cvar_t r_fullbright;
|
||||
extern cvar_t r_lightmap;
|
||||
extern cvar_t r_lightmapwide;
|
||||
extern cvar_t r_shadows;
|
||||
extern cvar_t r_wateralpha;
|
||||
extern cvar_t r_lavaalpha;
|
||||
extern cvar_t r_telealpha;
|
||||
extern cvar_t r_slimealpha;
|
||||
extern cvar_t r_litwater;
|
||||
extern cvar_t r_dynamic;
|
||||
extern cvar_t r_novis;
|
||||
extern cvar_t r_scale;
|
||||
|
||||
extern cvar_t gl_clear;
|
||||
extern cvar_t gl_cull;
|
||||
extern cvar_t gl_smoothmodels;
|
||||
extern cvar_t gl_affinemodels;
|
||||
extern cvar_t gl_polyblend;
|
||||
extern cvar_t gl_flashblend;
|
||||
extern cvar_t gl_nocolors;
|
||||
extern cvar_t gl_finish;
|
||||
|
||||
extern cvar_t gl_playermip;
|
||||
|
||||
extern cvar_t gl_subdivide_size;
|
||||
extern float load_subdivide_size; //johnfitz -- remember what subdivide_size value was when this map was loaded
|
||||
|
||||
extern int gl_stencilbits;
|
||||
|
||||
// Multitexture
|
||||
extern qboolean mtexenabled;
|
||||
extern qboolean gl_mtexable;
|
||||
extern PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc;
|
||||
extern PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc;
|
||||
extern PFNGLCLIENTACTIVETEXTUREARBPROC GL_ClientActiveTextureFunc;
|
||||
extern GLint gl_max_texture_units; //ericw
|
||||
|
||||
//johnfitz -- anisotropic filtering
|
||||
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
||||
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
|
||||
extern float gl_max_anisotropy;
|
||||
extern qboolean gl_anisotropy_able;
|
||||
|
||||
//ericw -- VBO
|
||||
extern PFNGLBINDBUFFERARBPROC GL_BindBufferFunc;
|
||||
extern PFNGLBUFFERDATAARBPROC GL_BufferDataFunc;
|
||||
extern PFNGLBUFFERSUBDATAARBPROC GL_BufferSubDataFunc;
|
||||
extern PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc;
|
||||
extern PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc;
|
||||
extern qboolean gl_vbo_able;
|
||||
//ericw
|
||||
|
||||
//ericw -- GLSL
|
||||
|
||||
// SDL 1.2 has a bug where it doesn't provide these typedefs on OS X!
|
||||
typedef GLuint (APIENTRYP QS_PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (APIENTRYP QS_PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP QS_PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP QS_PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
|
||||
typedef void (APIENTRYP QS_PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP QS_PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP QS_PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef void (APIENTRYP QS_PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP QS_PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
|
||||
typedef GLuint (APIENTRYP QS_PFNGLCREATEPROGRAMPROC) (void);
|
||||
typedef void (APIENTRYP QS_PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP QS_PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP QS_PFNGLBINDATTRIBLOCATIONFUNC) (GLuint program, GLuint index, const GLchar *name);
|
||||
typedef void (APIENTRYP QS_PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||
typedef GLint (APIENTRYP QS_PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP QS_PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
typedef void (APIENTRYP QS_PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef void (APIENTRYP QS_PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
|
||||
typedef GLint (APIENTRYP QS_PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
|
||||
typedef void (APIENTRYP QS_PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
|
||||
typedef void (APIENTRYP QS_PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
|
||||
typedef void (APIENTRYP QS_PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
|
||||
typedef void (APIENTRYP QS_PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||
typedef void (APIENTRYP QS_PFNGENERATEMIPMAP) (GLenum type);
|
||||
|
||||
extern QS_PFNGLCREATESHADERPROC GL_CreateShaderFunc;
|
||||
extern QS_PFNGLDELETESHADERPROC GL_DeleteShaderFunc;
|
||||
extern QS_PFNGLDELETEPROGRAMPROC GL_DeleteProgramFunc;
|
||||
extern QS_PFNGLSHADERSOURCEPROC GL_ShaderSourceFunc;
|
||||
extern QS_PFNGLCOMPILESHADERPROC GL_CompileShaderFunc;
|
||||
extern QS_PFNGLGETSHADERIVPROC GL_GetShaderivFunc;
|
||||
extern QS_PFNGLGETSHADERINFOLOGPROC GL_GetShaderInfoLogFunc;
|
||||
extern QS_PFNGLGETPROGRAMIVPROC GL_GetProgramivFunc;
|
||||
extern QS_PFNGLGETPROGRAMINFOLOGPROC GL_GetProgramInfoLogFunc;
|
||||
extern QS_PFNGLCREATEPROGRAMPROC GL_CreateProgramFunc;
|
||||
extern QS_PFNGLATTACHSHADERPROC GL_AttachShaderFunc;
|
||||
extern QS_PFNGLLINKPROGRAMPROC GL_LinkProgramFunc;
|
||||
extern QS_PFNGLBINDATTRIBLOCATIONFUNC GL_BindAttribLocationFunc;
|
||||
extern QS_PFNGLUSEPROGRAMPROC GL_UseProgramFunc;
|
||||
extern QS_PFNGLGETATTRIBLOCATIONPROC GL_GetAttribLocationFunc;
|
||||
extern QS_PFNGLVERTEXATTRIBPOINTERPROC GL_VertexAttribPointerFunc;
|
||||
extern QS_PFNGLENABLEVERTEXATTRIBARRAYPROC GL_EnableVertexAttribArrayFunc;
|
||||
extern QS_PFNGLDISABLEVERTEXATTRIBARRAYPROC GL_DisableVertexAttribArrayFunc;
|
||||
extern QS_PFNGLGETUNIFORMLOCATIONPROC GL_GetUniformLocationFunc;
|
||||
extern QS_PFNGLUNIFORM1IPROC GL_Uniform1iFunc;
|
||||
extern QS_PFNGLUNIFORM1FPROC GL_Uniform1fFunc;
|
||||
extern QS_PFNGLUNIFORM3FPROC GL_Uniform3fFunc;
|
||||
extern QS_PFNGLUNIFORM4FPROC GL_Uniform4fFunc;
|
||||
extern qboolean gl_glsl_able;
|
||||
extern qboolean gl_glsl_gamma_able;
|
||||
extern qboolean gl_glsl_alias_able;
|
||||
// ericw --
|
||||
|
||||
//mipmapped warp textures
|
||||
extern QS_PFNGENERATEMIPMAP GL_GenerateMipmap;
|
||||
|
||||
//ericw -- NPOT texture support
|
||||
extern qboolean gl_texture_NPOT;
|
||||
|
||||
//johnfitz -- polygon offset
|
||||
#define OFFSET_BMODEL 1
|
||||
#define OFFSET_NONE 0
|
||||
#define OFFSET_DECAL -1
|
||||
#define OFFSET_FOG -2
|
||||
#define OFFSET_SHOWTRIS -3
|
||||
void GL_PolygonOffset (int);
|
||||
|
||||
//GL_EXT_packed_pixels
|
||||
#ifndef GL_UNSIGNED_INT_10_10_10_2
|
||||
#define GL_UNSIGNED_INT_10_10_10_2 0x8036
|
||||
#endif
|
||||
extern qboolean gl_packed_pixels;
|
||||
|
||||
//johnfitz -- GL_EXT_texture_env_combine
|
||||
//the values for GL_ARB_ are identical
|
||||
#define GL_COMBINE_EXT 0x8570
|
||||
#define GL_COMBINE_RGB_EXT 0x8571
|
||||
#define GL_COMBINE_ALPHA_EXT 0x8572
|
||||
#define GL_RGB_SCALE_EXT 0x8573
|
||||
#define GL_CONSTANT_EXT 0x8576
|
||||
#define GL_PRIMARY_COLOR_EXT 0x8577
|
||||
#define GL_PREVIOUS_EXT 0x8578
|
||||
#define GL_SOURCE0_RGB_EXT 0x8580
|
||||
#define GL_SOURCE1_RGB_EXT 0x8581
|
||||
#define GL_SOURCE0_ALPHA_EXT 0x8588
|
||||
#define GL_SOURCE1_ALPHA_EXT 0x8589
|
||||
extern qboolean gl_texture_env_combine;
|
||||
extern qboolean gl_texture_env_add; // for GL_EXT_texture_env_add
|
||||
|
||||
//johnfitz -- rendering statistics
|
||||
extern int rs_brushpolys, rs_aliaspolys, rs_skypolys;
|
||||
extern int rs_dynamiclightmaps, rs_brushpasses, rs_aliaspasses, rs_skypasses;
|
||||
|
||||
//johnfitz -- track developer statistics that vary every frame
|
||||
extern cvar_t devstats;
|
||||
typedef struct {
|
||||
int packetsize;
|
||||
int edicts;
|
||||
int visedicts;
|
||||
int efrags;
|
||||
int tempents;
|
||||
int beams;
|
||||
int dlights;
|
||||
} devstats_t;
|
||||
extern devstats_t dev_stats, dev_peakstats;
|
||||
|
||||
//ohnfitz -- reduce overflow warning spam
|
||||
typedef struct {
|
||||
double packetsize;
|
||||
double efrags;
|
||||
double beams;
|
||||
double varstring;
|
||||
} overflowtimes_t;
|
||||
extern overflowtimes_t dev_overflows; //this stores the last time overflow messages were displayed, not the last time overflows occured
|
||||
#define CONSOLE_RESPAM_TIME 3 // seconds between repeated warning messages
|
||||
|
||||
//johnfitz -- moved here from r_brush.c
|
||||
extern int gl_lightmap_format, lightmap_bytes;
|
||||
|
||||
#define LMBLOCK_WIDTH 256 //FIXME: make dynamic. if we have a decent card there's no real reason not to use 4k or 16k (assuming there's no lightstyles/dynamics that need uploading...)
|
||||
#define LMBLOCK_HEIGHT 256 //Alternatively, use texture arrays, which would avoid the need to switch textures as often.
|
||||
|
||||
typedef struct glRect_s {
|
||||
unsigned short l,t,w,h;
|
||||
} glRect_t;
|
||||
struct lightmap_s
|
||||
{
|
||||
gltexture_t *texture;
|
||||
glpoly_t *polys;
|
||||
qboolean modified;
|
||||
glRect_t rectchange;
|
||||
|
||||
// the lightmap texture data needs to be kept in
|
||||
// main memory so texsubimage can update properly
|
||||
byte *data;//[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT];
|
||||
};
|
||||
extern struct lightmap_s *lightmaps;
|
||||
extern int lightmap_count; //allocated lightmaps
|
||||
|
||||
extern int gl_warpimagesize; //johnfitz -- for water warp
|
||||
|
||||
extern qboolean r_drawflat_cheatsafe, r_fullbright_cheatsafe, r_lightmap_cheatsafe, r_drawworld_cheatsafe; //johnfitz
|
||||
|
||||
typedef struct glsl_attrib_binding_s {
|
||||
const char *name;
|
||||
GLuint attrib;
|
||||
} glsl_attrib_binding_t;
|
||||
|
||||
extern float map_wateralpha, map_lavaalpha, map_telealpha, map_slimealpha; //ericw
|
||||
|
||||
#define NUMVERTEXNORMALS 162
|
||||
extern const float r_avertexnormals[NUMVERTEXNORMALS][3];
|
||||
|
||||
//johnfitz -- fog functions called from outside gl_fog.c
|
||||
void Fog_ParseServerMessage (void);
|
||||
float *Fog_GetColor (void);
|
||||
float Fog_GetDensity (void);
|
||||
void Fog_EnableGFog (void);
|
||||
void Fog_DisableGFog (void);
|
||||
void Fog_StartAdditive (void);
|
||||
void Fog_StopAdditive (void);
|
||||
void Fog_SetupFrame (void);
|
||||
void Fog_NewMap (void);
|
||||
void Fog_Init (void);
|
||||
void Fog_SetupState (void);
|
||||
|
||||
void R_NewGame (void);
|
||||
|
||||
void R_AnimateLight (void);
|
||||
void R_MarkSurfaces (void);
|
||||
qboolean R_CullBox (vec3_t emins, vec3_t emaxs);
|
||||
void R_StoreEfrags (efrag_t **ppefrag);
|
||||
qboolean R_CullModelForEntity (entity_t *e);
|
||||
void R_RotateForEntity (vec3_t origin, vec3_t angles, unsigned char scale);
|
||||
void R_MarkLights (dlight_t *light, int num, mnode_t *node);
|
||||
|
||||
void R_InitParticles (void);
|
||||
void R_DrawParticles (void);
|
||||
void CL_RunParticles (void);
|
||||
void R_ClearParticles (void);
|
||||
|
||||
void R_TranslatePlayerSkin (int playernum);
|
||||
void R_TranslateNewPlayerSkin (int playernum); //johnfitz -- this handles cases when the actual texture changes
|
||||
void R_UpdateWarpTextures (void);
|
||||
|
||||
void R_DrawWorld (void);
|
||||
void R_DrawAliasModel (entity_t *e);
|
||||
void R_DrawBrushModel (entity_t *e);
|
||||
void R_DrawSpriteModel (entity_t *e);
|
||||
|
||||
void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain);
|
||||
|
||||
void R_RenderDlights (void);
|
||||
void GL_BuildLightmaps (void);
|
||||
void GL_DeleteBModelVertexBuffer (void);
|
||||
void GL_BuildBModelVertexBuffer (void);
|
||||
void GLMesh_LoadVertexBuffers (void);
|
||||
void GLMesh_DeleteVertexBuffers (void);
|
||||
void R_RebuildAllLightmaps (void);
|
||||
|
||||
int R_LightPoint (vec3_t p);
|
||||
|
||||
void GL_SubdivideSurface (msurface_t *fa);
|
||||
void R_BuildLightMap (msurface_t *surf, byte *dest, int stride);
|
||||
void R_RenderDynamicLightmaps (msurface_t *fa);
|
||||
void R_UploadLightmaps (void);
|
||||
|
||||
void R_DrawWorld_ShowTris (void);
|
||||
void R_DrawBrushModel_ShowTris (entity_t *e);
|
||||
void R_DrawAliasModel_ShowTris (entity_t *e);
|
||||
void R_DrawParticles_ShowTris (void);
|
||||
|
||||
GLint GL_GetUniformLocation (GLuint *programPtr, const char *name);
|
||||
GLuint GL_CreateProgram (const GLchar *vertSource, const GLchar *fragSource, int numbindings, const glsl_attrib_binding_t *bindings);
|
||||
void R_DeleteShaders (void);
|
||||
|
||||
void GLWorld_CreateShaders (void);
|
||||
void GLAlias_CreateShaders (void);
|
||||
void GL_DrawAliasShadow (entity_t *e);
|
||||
void DrawGLTriangleFan (glpoly_t *p);
|
||||
void DrawGLPoly (glpoly_t *p);
|
||||
void DrawWaterPoly (glpoly_t *p);
|
||||
void GL_MakeAliasModelDisplayLists (qmodel_t *m, aliashdr_t *hdr);
|
||||
|
||||
void Sky_Init (void);
|
||||
void Sky_ClearAll (void);
|
||||
void Sky_DrawSky (void);
|
||||
void Sky_NewMap (void);
|
||||
void Sky_LoadTexture (qmodel_t *m, texture_t *mt);
|
||||
void Sky_LoadTextureQ64 (qmodel_t *m, texture_t *mt);
|
||||
void Sky_LoadSkyBox (const char *name);
|
||||
|
||||
void TexMgr_RecalcWarpImageSize (void);
|
||||
|
||||
void R_ClearTextureChains (qmodel_t *mod, texchain_t chain);
|
||||
void R_ChainSurface (msurface_t *surf, texchain_t chain);
|
||||
void R_DrawTextureChains (qmodel_t *model, entity_t *ent, texchain_t chain);
|
||||
void R_DrawWorld_Water (void);
|
||||
|
||||
void GL_BindBuffer (GLenum target, GLuint buffer);
|
||||
void GL_ClearBufferBindings (void);
|
||||
|
||||
void GLSLGamma_DeleteTexture (void);
|
||||
void GLSLGamma_GammaCorrect (void);
|
||||
|
||||
void R_ScaleView_DeleteTexture (void);
|
||||
|
||||
float GL_WaterAlphaForSurface (msurface_t *fa);
|
||||
|
||||
#endif /* GLQUAKE_H */
|
||||
+947
@@ -0,0 +1,947 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2007-2008 Kristian Duske
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// host.c -- coordinates spawning and killing of local servers
|
||||
|
||||
#include "quakedef.hpp"
|
||||
#include "bgmusic.hpp"
|
||||
#include <csetjmp>
|
||||
|
||||
/*
|
||||
|
||||
A server can allways be started, even if the system started out as a client
|
||||
to a remote system.
|
||||
|
||||
A client can NOT be started if the system started as a dedicated server.
|
||||
|
||||
Memory is cleared / released when a server or client begins, not when they end.
|
||||
|
||||
*/
|
||||
|
||||
quakeparms_t *host_parms;
|
||||
|
||||
qboolean host_initialized; // true if into command execution
|
||||
|
||||
double host_frametime;
|
||||
double realtime; // without any filtering or bounding
|
||||
double oldrealtime; // last frame run
|
||||
|
||||
int host_framecount;
|
||||
|
||||
int host_hunklevel;
|
||||
|
||||
int minimum_memory;
|
||||
|
||||
client_t *host_client; // current client
|
||||
|
||||
jmp_buf host_abortserver;
|
||||
|
||||
byte *host_colormap;
|
||||
|
||||
cvar_t host_framerate = {"host_framerate","0",CVAR_NONE}; // set for slow motion
|
||||
cvar_t host_speeds = {"host_speeds","0",CVAR_NONE}; // set for running times
|
||||
cvar_t host_maxfps = {"host_maxfps", "72", CVAR_ARCHIVE}; //johnfitz
|
||||
cvar_t host_timescale = {"host_timescale", "0", CVAR_NONE}; //johnfitz
|
||||
cvar_t max_edicts = {"max_edicts", "8192", CVAR_NONE}; //johnfitz //ericw -- changed from 2048 to 8192, removed CVAR_ARCHIVE
|
||||
|
||||
cvar_t sys_ticrate = {"sys_ticrate","0.05",CVAR_NONE}; // dedicated server
|
||||
cvar_t serverprofile = {"serverprofile","0",CVAR_NONE};
|
||||
|
||||
cvar_t fraglimit = {"fraglimit","0",CVAR_NOTIFY|CVAR_SERVERINFO};
|
||||
cvar_t timelimit = {"timelimit","0",CVAR_NOTIFY|CVAR_SERVERINFO};
|
||||
cvar_t teamplay = {"teamplay","0",CVAR_NOTIFY|CVAR_SERVERINFO};
|
||||
cvar_t samelevel = {"samelevel","0",CVAR_NONE};
|
||||
cvar_t noexit = {"noexit","0",CVAR_NOTIFY|CVAR_SERVERINFO};
|
||||
cvar_t skill = {"skill","1",CVAR_NONE}; // 0 - 3
|
||||
cvar_t deathmatch = {"deathmatch","0",CVAR_NONE}; // 0, 1, or 2
|
||||
cvar_t coop = {"coop","0",CVAR_NONE}; // 0 or 1
|
||||
|
||||
cvar_t pausable = {"pausable","1",CVAR_NONE};
|
||||
|
||||
cvar_t developer = {"developer","0",CVAR_NONE};
|
||||
|
||||
cvar_t temp1 = {"temp1","0",CVAR_NONE};
|
||||
|
||||
cvar_t devstats = {"devstats","0",CVAR_NONE}; //johnfitz -- track developer statistics that vary every frame
|
||||
|
||||
cvar_t campaign = {"campaign","0",CVAR_NONE}; // for the 2021 rerelease
|
||||
cvar_t horde = {"horde","0",CVAR_NONE}; // for the 2021 rerelease
|
||||
cvar_t sv_cheats = {"sv_cheats","0",CVAR_NONE}; // for the 2021 rerelease
|
||||
|
||||
devstats_t dev_stats, dev_peakstats;
|
||||
overflowtimes_t dev_overflows; //this stores the last time overflow messages were displayed, not the last time overflows occured
|
||||
|
||||
/*
|
||||
================
|
||||
Max_Edicts_f -- johnfitz
|
||||
================
|
||||
*/
|
||||
static void Max_Edicts_f (cvar_t *var)
|
||||
{
|
||||
//TODO: clamp it here?
|
||||
if (cls.state == ca_connected || sv.active)
|
||||
Con_Printf ("Changes to max_edicts will not take effect until the next time a map is loaded.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Max_Fps_f -- ericw
|
||||
================
|
||||
*/
|
||||
static void Max_Fps_f (cvar_t *var)
|
||||
{
|
||||
if (var->value > 72)
|
||||
Con_Warning ("host_maxfps above 72 breaks physics.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Host_EndGame
|
||||
================
|
||||
*/
|
||||
void Host_EndGame (const char *message, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char string[1024];
|
||||
|
||||
va_start (argptr,message);
|
||||
q_vsnprintf (string, sizeof(string), message, argptr);
|
||||
va_end (argptr);
|
||||
Con_DPrintf ("Host_EndGame: %s\n",string);
|
||||
|
||||
if (sv.active)
|
||||
Host_ShutdownServer (false);
|
||||
|
||||
if (cls.state == ca_dedicated)
|
||||
Sys_Error ("Host_EndGame: %s\n",string); // dedicated servers exit
|
||||
|
||||
if (cls.demonum != -1 && !cls.timedemo)
|
||||
CL_NextDemo ();
|
||||
else
|
||||
CL_Disconnect ();
|
||||
|
||||
longjmp (host_abortserver, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Host_Error
|
||||
|
||||
This shuts down both the client and server
|
||||
================
|
||||
*/
|
||||
void Host_Error (const char *error, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char string[1024];
|
||||
static qboolean inerror = false;
|
||||
|
||||
if (inerror)
|
||||
Sys_Error ("Host_Error: recursively entered");
|
||||
inerror = true;
|
||||
|
||||
SCR_EndLoadingPlaque (); // reenable screen updates
|
||||
|
||||
va_start (argptr,error);
|
||||
q_vsnprintf (string, sizeof(string), error, argptr);
|
||||
va_end (argptr);
|
||||
Con_Printf ("Host_Error: %s\n",string);
|
||||
|
||||
if (sv.active)
|
||||
Host_ShutdownServer (false);
|
||||
|
||||
if (cls.state == ca_dedicated)
|
||||
Sys_Error ("Host_Error: %s\n",string); // dedicated servers exit
|
||||
|
||||
CL_Disconnect ();
|
||||
cls.demonum = -1;
|
||||
cl.intermission = 0; //johnfitz -- for errors during intermissions (changelevel with no map found, etc.)
|
||||
|
||||
inerror = false;
|
||||
|
||||
longjmp (host_abortserver, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Host_FindMaxClients
|
||||
================
|
||||
*/
|
||||
void Host_FindMaxClients (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
svs.maxclients = 1;
|
||||
|
||||
i = COM_CheckParm ("-dedicated");
|
||||
if (i)
|
||||
{
|
||||
cls.state = ca_dedicated;
|
||||
if (i != (com_argc - 1))
|
||||
{
|
||||
svs.maxclients = Q_atoi (com_argv[i+1]);
|
||||
}
|
||||
else
|
||||
svs.maxclients = 8;
|
||||
}
|
||||
else
|
||||
cls.state = ca_disconnected;
|
||||
|
||||
i = COM_CheckParm ("-listen");
|
||||
if (i)
|
||||
{
|
||||
if (cls.state == ca_dedicated)
|
||||
Sys_Error ("Only one of -dedicated or -listen can be specified");
|
||||
if (i != (com_argc - 1))
|
||||
svs.maxclients = Q_atoi (com_argv[i+1]);
|
||||
else
|
||||
svs.maxclients = 8;
|
||||
}
|
||||
if (svs.maxclients < 1)
|
||||
svs.maxclients = 8;
|
||||
else if (svs.maxclients > MAX_SCOREBOARD)
|
||||
svs.maxclients = MAX_SCOREBOARD;
|
||||
|
||||
svs.maxclientslimit = svs.maxclients;
|
||||
if (svs.maxclientslimit < 4)
|
||||
svs.maxclientslimit = 4;
|
||||
svs.clients = (struct client_s *) Hunk_AllocName (svs.maxclientslimit*sizeof(client_t), "clients");
|
||||
|
||||
if (svs.maxclients > 1)
|
||||
Cvar_SetQuick (&deathmatch, "1");
|
||||
else
|
||||
Cvar_SetQuick (&deathmatch, "0");
|
||||
}
|
||||
|
||||
void Host_Version_f (void)
|
||||
{
|
||||
Con_Printf ("Quake Version %1.2f\n", VERSION);
|
||||
Con_Printf ("QuakeSpasm Version " QUAKESPASM_VER_STRING "\n");
|
||||
Con_Printf ("Exe: " __TIME__ " " __DATE__ "\n");
|
||||
}
|
||||
|
||||
/* cvar callback functions : */
|
||||
void Host_Callback_Notify (cvar_t *var)
|
||||
{
|
||||
if (sv.active)
|
||||
SV_BroadcastPrintf ("\"%s\" changed to \"%s\"\n", var->name, var->string);
|
||||
}
|
||||
|
||||
/*
|
||||
=======================
|
||||
Host_InitLocal
|
||||
======================
|
||||
*/
|
||||
void Host_InitLocal (void)
|
||||
{
|
||||
Cmd_AddCommand ("version", Host_Version_f);
|
||||
|
||||
Host_InitCommands ();
|
||||
|
||||
Cvar_RegisterVariable (&host_framerate);
|
||||
Cvar_RegisterVariable (&host_speeds);
|
||||
Cvar_RegisterVariable (&host_maxfps); //johnfitz
|
||||
Cvar_SetCallback (&host_maxfps, Max_Fps_f);
|
||||
Cvar_RegisterVariable (&host_timescale); //johnfitz
|
||||
|
||||
Cvar_RegisterVariable (&max_edicts); //johnfitz
|
||||
Cvar_SetCallback (&max_edicts, Max_Edicts_f);
|
||||
Cvar_RegisterVariable (&devstats); //johnfitz
|
||||
|
||||
Cvar_RegisterVariable (&sys_ticrate);
|
||||
Cvar_RegisterVariable (&sys_throttle);
|
||||
Cvar_RegisterVariable (&serverprofile);
|
||||
|
||||
Cvar_RegisterVariable (&fraglimit);
|
||||
Cvar_RegisterVariable (&timelimit);
|
||||
Cvar_RegisterVariable (&teamplay);
|
||||
Cvar_SetCallback (&fraglimit, Host_Callback_Notify);
|
||||
Cvar_SetCallback (&timelimit, Host_Callback_Notify);
|
||||
Cvar_SetCallback (&teamplay, Host_Callback_Notify);
|
||||
Cvar_RegisterVariable (&samelevel);
|
||||
Cvar_RegisterVariable (&noexit);
|
||||
Cvar_SetCallback (&noexit, Host_Callback_Notify);
|
||||
Cvar_RegisterVariable (&skill);
|
||||
Cvar_RegisterVariable (&developer);
|
||||
Cvar_RegisterVariable (&coop);
|
||||
Cvar_RegisterVariable (&deathmatch);
|
||||
|
||||
Cvar_RegisterVariable (&campaign);
|
||||
Cvar_RegisterVariable (&horde);
|
||||
Cvar_RegisterVariable (&sv_cheats);
|
||||
|
||||
Cvar_RegisterVariable (&pausable);
|
||||
|
||||
Cvar_RegisterVariable (&temp1);
|
||||
|
||||
Host_FindMaxClients ();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Host_WriteConfiguration
|
||||
|
||||
Writes key bindings and archived cvars to config.cfg
|
||||
===============
|
||||
*/
|
||||
void Host_WriteConfiguration (void)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
// dedicated servers initialize the host but don't parse and set the
|
||||
// config.cfg cvars
|
||||
if (host_initialized && !isDedicated && !host_parms->errstate)
|
||||
{
|
||||
f = fopen (va("%s/config.cfg", com_gamedir), "w");
|
||||
if (!f)
|
||||
{
|
||||
Con_Printf ("Couldn't write config.cfg.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//VID_SyncCvars (); //johnfitz -- write actual current mode to config file, in case cvars were messed with
|
||||
|
||||
Key_WriteBindings (f);
|
||||
Cvar_WriteVariables (f);
|
||||
|
||||
//johnfitz -- extra commands to preserve state
|
||||
fprintf (f, "vid_restart\n");
|
||||
if (in_mlook.state & 1) fprintf (f, "+mlook\n");
|
||||
//johnfitz
|
||||
|
||||
fclose (f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_ClientPrintf
|
||||
|
||||
Sends text across to be displayed
|
||||
FIXME: make this just a stuffed echo?
|
||||
=================
|
||||
*/
|
||||
void SV_ClientPrintf (const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char string[1024];
|
||||
|
||||
va_start (argptr,fmt);
|
||||
q_vsnprintf (string, sizeof(string), fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
MSG_WriteByte (&host_client->message, svc_print);
|
||||
MSG_WriteString (&host_client->message, string);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SV_BroadcastPrintf
|
||||
|
||||
Sends text to all active clients
|
||||
=================
|
||||
*/
|
||||
void SV_BroadcastPrintf (const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char string[1024];
|
||||
int i;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
q_vsnprintf (string, sizeof(string), fmt, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
for (i = 0; i < svs.maxclients; i++)
|
||||
{
|
||||
if (svs.clients[i].active && svs.clients[i].spawned)
|
||||
{
|
||||
MSG_WriteByte (&svs.clients[i].message, svc_print);
|
||||
MSG_WriteString (&svs.clients[i].message, string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Host_ClientCommands
|
||||
|
||||
Send text over to the client to be executed
|
||||
=================
|
||||
*/
|
||||
void Host_ClientCommands (const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char string[1024];
|
||||
|
||||
va_start (argptr,fmt);
|
||||
q_vsnprintf (string, sizeof(string), fmt, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
MSG_WriteByte (&host_client->message, svc_stufftext);
|
||||
MSG_WriteString (&host_client->message, string);
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
SV_DropClient
|
||||
|
||||
Called when the player is getting totally kicked off the host
|
||||
if (crash = true), don't bother sending signofs
|
||||
=====================
|
||||
*/
|
||||
void SV_DropClient (qboolean crash)
|
||||
{
|
||||
int saveSelf;
|
||||
int i;
|
||||
client_t *client;
|
||||
|
||||
if (!crash)
|
||||
{
|
||||
// send any final messages (don't check for errors)
|
||||
if (NET_CanSendMessage (host_client->netconnection))
|
||||
{
|
||||
MSG_WriteByte (&host_client->message, svc_disconnect);
|
||||
NET_SendMessage (host_client->netconnection, &host_client->message);
|
||||
}
|
||||
|
||||
if (host_client->edict && host_client->spawned)
|
||||
{
|
||||
// call the prog function for removing a client
|
||||
// this will set the body to a dead frame, among other things
|
||||
saveSelf = pr_global_struct->self;
|
||||
pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
|
||||
PR_ExecuteProgram (pr_global_struct->ClientDisconnect);
|
||||
pr_global_struct->self = saveSelf;
|
||||
}
|
||||
|
||||
Sys_Printf ("Client %s removed\n",host_client->name);
|
||||
}
|
||||
|
||||
// break the net connection
|
||||
NET_Close (host_client->netconnection);
|
||||
host_client->netconnection = NULL;
|
||||
|
||||
// free the client (the body stays around)
|
||||
host_client->active = false;
|
||||
host_client->name[0] = 0;
|
||||
host_client->old_frags = -999999;
|
||||
net_activeconnections--;
|
||||
|
||||
// send notification to all clients
|
||||
for (i = 0, client = svs.clients; i < svs.maxclients; i++, client++)
|
||||
{
|
||||
if (!client->active)
|
||||
continue;
|
||||
MSG_WriteByte (&client->message, svc_updatename);
|
||||
MSG_WriteByte (&client->message, host_client - svs.clients);
|
||||
MSG_WriteString (&client->message, "");
|
||||
MSG_WriteByte (&client->message, svc_updatefrags);
|
||||
MSG_WriteByte (&client->message, host_client - svs.clients);
|
||||
MSG_WriteShort (&client->message, 0);
|
||||
MSG_WriteByte (&client->message, svc_updatecolors);
|
||||
MSG_WriteByte (&client->message, host_client - svs.clients);
|
||||
MSG_WriteByte (&client->message, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Host_ShutdownServer
|
||||
|
||||
This only happens at the end of a game, not between levels
|
||||
==================
|
||||
*/
|
||||
void Host_ShutdownServer(qboolean crash)
|
||||
{
|
||||
int i;
|
||||
int count;
|
||||
sizebuf_t buf;
|
||||
byte message[4];
|
||||
double start;
|
||||
|
||||
if (!sv.active)
|
||||
return;
|
||||
|
||||
sv.active = false;
|
||||
|
||||
// stop all client sounds immediately
|
||||
if (cls.state == ca_connected)
|
||||
CL_Disconnect ();
|
||||
|
||||
// flush any pending messages - like the score!!!
|
||||
start = Sys_DoubleTime();
|
||||
do
|
||||
{
|
||||
count = 0;
|
||||
for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++)
|
||||
{
|
||||
if (host_client->active && host_client->message.cursize)
|
||||
{
|
||||
if (NET_CanSendMessage (host_client->netconnection))
|
||||
{
|
||||
NET_SendMessage(host_client->netconnection, &host_client->message);
|
||||
SZ_Clear (&host_client->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
NET_GetMessage(host_client->netconnection);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((Sys_DoubleTime() - start) > 3.0)
|
||||
break;
|
||||
}
|
||||
while (count);
|
||||
|
||||
// make sure all the clients know we're disconnecting
|
||||
buf.data = message;
|
||||
buf.maxsize = 4;
|
||||
buf.cursize = 0;
|
||||
MSG_WriteByte(&buf, svc_disconnect);
|
||||
count = NET_SendToAll(&buf, 5.0);
|
||||
if (count)
|
||||
Con_Printf("Host_ShutdownServer: NET_SendToAll failed for %u clients\n", count);
|
||||
|
||||
for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++)
|
||||
if (host_client->active)
|
||||
SV_DropClient(crash);
|
||||
|
||||
//
|
||||
// clear structures
|
||||
//
|
||||
// memset (&sv, 0, sizeof(sv)); // ServerSpawn already do this by Host_ClearMemory
|
||||
memset (svs.clients, 0, svs.maxclientslimit*sizeof(client_t));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Host_ClearMemory
|
||||
|
||||
This clears all the memory used by both the client and server, but does
|
||||
not reinitialize anything.
|
||||
================
|
||||
*/
|
||||
void Host_ClearMemory (void)
|
||||
{
|
||||
Con_DPrintf ("Clearing memory\n");
|
||||
D_FlushCaches ();
|
||||
Mod_ClearAll ();
|
||||
Sky_ClearAll();
|
||||
/* host_hunklevel MUST be set at this point */
|
||||
Hunk_FreeToLowMark (host_hunklevel);
|
||||
cls.signon = 0; // not CL_ClearSignons()
|
||||
free(sv.edicts); // ericw -- sv.edicts switched to use malloc()
|
||||
memset (&sv, 0, sizeof(sv));
|
||||
memset (&cl, 0, sizeof(cl));
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// Host Frame
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
/*
|
||||
===================
|
||||
Host_FilterTime
|
||||
|
||||
Returns false if the time is too short to run a frame
|
||||
===================
|
||||
*/
|
||||
qboolean Host_FilterTime (float time)
|
||||
{
|
||||
float maxfps; //johnfitz
|
||||
|
||||
realtime += time;
|
||||
|
||||
//johnfitz -- max fps cvar
|
||||
maxfps = CLAMP (10.f, host_maxfps.value, 1000.f);
|
||||
if (!cls.timedemo && realtime - oldrealtime < 1.0/maxfps)
|
||||
return false; // framerate is too high
|
||||
//johnfitz
|
||||
|
||||
host_frametime = realtime - oldrealtime;
|
||||
oldrealtime = realtime;
|
||||
|
||||
//johnfitz -- host_timescale is more intuitive than host_framerate
|
||||
if (host_timescale.value > 0)
|
||||
host_frametime *= host_timescale.value;
|
||||
//johnfitz
|
||||
else if (host_framerate.value > 0)
|
||||
host_frametime = host_framerate.value;
|
||||
else // don't allow really long or short frames
|
||||
host_frametime = CLAMP (0.001, host_frametime, 0.1); //johnfitz -- use CLAMP
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Host_GetConsoleCommands
|
||||
|
||||
Add them exactly as if they had been typed at the console
|
||||
===================
|
||||
*/
|
||||
void Host_GetConsoleCommands (void)
|
||||
{
|
||||
const char *cmd;
|
||||
|
||||
if (!isDedicated)
|
||||
return; // no stdin necessary in graphical mode
|
||||
|
||||
while (1)
|
||||
{
|
||||
cmd = Sys_ConsoleInput ();
|
||||
if (!cmd)
|
||||
break;
|
||||
Cbuf_AddText (cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Host_ServerFrame
|
||||
==================
|
||||
*/
|
||||
void Host_ServerFrame (void)
|
||||
{
|
||||
int i, active; //johnfitz
|
||||
edict_t *ent; //johnfitz
|
||||
|
||||
// run the world state
|
||||
pr_global_struct->frametime = host_frametime;
|
||||
|
||||
// set the time and clear the general datagram
|
||||
SV_ClearDatagram ();
|
||||
|
||||
// check for new clients
|
||||
SV_CheckForNewClients ();
|
||||
|
||||
// read client messages
|
||||
SV_RunClients ();
|
||||
|
||||
// move things around and think
|
||||
// always pause in single player if in console or menus
|
||||
if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) )
|
||||
SV_Physics ();
|
||||
|
||||
//johnfitz -- devstats
|
||||
if (cls.signon == SIGNONS)
|
||||
{
|
||||
for (i=0, active=0; i<sv.num_edicts; i++)
|
||||
{
|
||||
ent = EDICT_NUM(i);
|
||||
if (!ent->free)
|
||||
active++;
|
||||
}
|
||||
if (active > 600 && dev_peakstats.edicts <= 600)
|
||||
Con_DWarning ("%i edicts exceeds standard limit of 600 (max = %d).\n", active, sv.max_edicts);
|
||||
dev_stats.edicts = active;
|
||||
dev_peakstats.edicts = q_max(active, dev_peakstats.edicts);
|
||||
}
|
||||
//johnfitz
|
||||
|
||||
// send all messages to the clients
|
||||
SV_SendClientMessages ();
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Host_Frame
|
||||
|
||||
Runs all active servers
|
||||
==================
|
||||
*/
|
||||
void _Host_Frame (float time)
|
||||
{
|
||||
static double time1 = 0;
|
||||
static double time2 = 0;
|
||||
static double time3 = 0;
|
||||
int pass1, pass2, pass3;
|
||||
|
||||
if (setjmp (host_abortserver) )
|
||||
return; // something bad happened, or the server disconnected
|
||||
|
||||
// keep the random time dependent
|
||||
rand ();
|
||||
|
||||
// decide the simulation time
|
||||
if (!Host_FilterTime (time))
|
||||
return; // don't run too fast, or packets will flood out
|
||||
|
||||
// get new key events
|
||||
Key_UpdateForDest ();
|
||||
IN_UpdateInputMode ();
|
||||
Sys_SendKeyEvents ();
|
||||
|
||||
// allow mice or other external controllers to add commands
|
||||
IN_Commands ();
|
||||
|
||||
// process console commands
|
||||
Cbuf_Execute ();
|
||||
|
||||
NET_Poll();
|
||||
|
||||
// if running the server locally, make intentions now
|
||||
if (sv.active)
|
||||
CL_SendCmd ();
|
||||
|
||||
//-------------------
|
||||
//
|
||||
// server operations
|
||||
//
|
||||
//-------------------
|
||||
|
||||
// check for commands typed to the host
|
||||
Host_GetConsoleCommands ();
|
||||
|
||||
if (sv.active)
|
||||
Host_ServerFrame ();
|
||||
|
||||
//-------------------
|
||||
//
|
||||
// client operations
|
||||
//
|
||||
//-------------------
|
||||
|
||||
// if running the server remotely, send intentions now after
|
||||
// the incoming messages have been read
|
||||
if (!sv.active)
|
||||
CL_SendCmd ();
|
||||
|
||||
// fetch results from server
|
||||
if (cls.state == ca_connected)
|
||||
CL_ReadFromServer ();
|
||||
|
||||
// update video
|
||||
if (host_speeds.value)
|
||||
time1 = Sys_DoubleTime ();
|
||||
|
||||
SCR_UpdateScreen ();
|
||||
|
||||
CL_RunParticles (); //johnfitz -- seperated from rendering
|
||||
|
||||
if (host_speeds.value)
|
||||
time2 = Sys_DoubleTime ();
|
||||
|
||||
// update audio
|
||||
BGM_Update(); // adds music raw samples and/or advances midi driver
|
||||
if (cls.signon == SIGNONS)
|
||||
{
|
||||
S_Update (r_origin, vpn, vright, vup);
|
||||
CL_DecayLights ();
|
||||
}
|
||||
else
|
||||
S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin);
|
||||
|
||||
CDAudio_Update();
|
||||
|
||||
if (host_speeds.value)
|
||||
{
|
||||
pass1 = (time1 - time3)*1000;
|
||||
time3 = Sys_DoubleTime ();
|
||||
pass2 = (time2 - time1)*1000;
|
||||
pass3 = (time3 - time2)*1000;
|
||||
Con_Printf ("%3i tot %3i server %3i gfx %3i snd\n",
|
||||
pass1+pass2+pass3, pass1, pass2, pass3);
|
||||
}
|
||||
|
||||
host_framecount++;
|
||||
|
||||
}
|
||||
|
||||
void Host_Frame (float time)
|
||||
{
|
||||
double time1, time2;
|
||||
static double timetotal;
|
||||
static int timecount;
|
||||
int i, c, m;
|
||||
|
||||
if (!serverprofile.value)
|
||||
{
|
||||
_Host_Frame (time);
|
||||
return;
|
||||
}
|
||||
|
||||
time1 = Sys_DoubleTime ();
|
||||
_Host_Frame (time);
|
||||
time2 = Sys_DoubleTime ();
|
||||
|
||||
timetotal += time2 - time1;
|
||||
timecount++;
|
||||
|
||||
if (timecount < 1000)
|
||||
return;
|
||||
|
||||
m = timetotal*1000/timecount;
|
||||
timecount = 0;
|
||||
timetotal = 0;
|
||||
c = 0;
|
||||
for (i = 0; i < svs.maxclients; i++)
|
||||
{
|
||||
if (svs.clients[i].active)
|
||||
c++;
|
||||
}
|
||||
|
||||
Con_Printf ("serverprofile: %2i clients %2i msec\n", c, m);
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Host_Init
|
||||
====================
|
||||
*/
|
||||
void Host_Init (void)
|
||||
{
|
||||
if (standard_quake)
|
||||
minimum_memory = MINIMUM_MEMORY;
|
||||
else minimum_memory = MINIMUM_MEMORY_LEVELPAK;
|
||||
|
||||
if (COM_CheckParm ("-minmemory"))
|
||||
host_parms->memsize = minimum_memory;
|
||||
|
||||
if (host_parms->memsize < minimum_memory)
|
||||
Sys_Error ("Only %4.1f megs of memory available, can't execute game", host_parms->memsize / (float)0x100000);
|
||||
|
||||
com_argc = host_parms->argc;
|
||||
com_argv = host_parms->argv;
|
||||
|
||||
Memory_Init (host_parms->membase, host_parms->memsize);
|
||||
Cbuf_Init ();
|
||||
Cmd_Init ();
|
||||
LOG_Init (host_parms);
|
||||
Cvar_Init (); //johnfitz
|
||||
COM_Init ();
|
||||
COM_InitFilesystem ();
|
||||
Host_InitLocal ();
|
||||
W_LoadWadFile (); //johnfitz -- filename is now hard-coded for honesty
|
||||
if (cls.state != ca_dedicated)
|
||||
{
|
||||
Key_Init ();
|
||||
Con_Init ();
|
||||
}
|
||||
PR_Init ();
|
||||
Mod_Init ();
|
||||
NET_Init ();
|
||||
SV_Init ();
|
||||
|
||||
Con_Printf ("Exe: " __TIME__ " " __DATE__ "\n");
|
||||
Con_Printf ("%4.1f megabyte heap\n", host_parms->memsize/ (1024*1024.0));
|
||||
|
||||
if (cls.state != ca_dedicated)
|
||||
{
|
||||
host_colormap = (byte *)COM_LoadHunkFile ("gfx/colormap.lmp", NULL);
|
||||
if (!host_colormap)
|
||||
Sys_Error ("Couldn't load gfx/colormap.lmp");
|
||||
|
||||
V_Init ();
|
||||
Chase_Init ();
|
||||
M_Init ();
|
||||
ExtraMaps_Init (); //johnfitz
|
||||
Modlist_Init (); //johnfitz
|
||||
DemoList_Init (); //ericw
|
||||
VID_Init ();
|
||||
IN_Init ();
|
||||
TexMgr_Init (); //johnfitz
|
||||
Draw_Init ();
|
||||
SCR_Init ();
|
||||
R_Init ();
|
||||
S_Init ();
|
||||
CDAudio_Init ();
|
||||
BGM_Init();
|
||||
Sbar_Init ();
|
||||
CL_Init ();
|
||||
}
|
||||
|
||||
LOC_Init (); // for 2021 rerelease support.
|
||||
|
||||
Hunk_AllocName (0, "-HOST_HUNKLEVEL-");
|
||||
host_hunklevel = Hunk_LowMark ();
|
||||
|
||||
host_initialized = true;
|
||||
Con_Printf ("\n========= Quake Initialized =========\n\n");
|
||||
|
||||
if (cls.state != ca_dedicated)
|
||||
{
|
||||
Cbuf_InsertText ("exec quake.rc\n");
|
||||
// johnfitz -- in case the vid mode was locked during vid_init, we can unlock it now.
|
||||
// note: two leading newlines because the command buffer swallows one of them.
|
||||
Cbuf_AddText ("\n\nvid_unlock\n");
|
||||
}
|
||||
|
||||
if (cls.state == ca_dedicated)
|
||||
{
|
||||
Cbuf_AddText ("exec autoexec.cfg\n");
|
||||
Cbuf_AddText ("stuffcmds");
|
||||
Cbuf_Execute ();
|
||||
if (!sv.active)
|
||||
Cbuf_AddText ("map start\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Host_Shutdown
|
||||
|
||||
FIXME: this is a callback from Sys_Quit and Sys_Error. It would be better
|
||||
to run quit through here before the final handoff to the sys code.
|
||||
===============
|
||||
*/
|
||||
void Host_Shutdown(void)
|
||||
{
|
||||
static qboolean isdown = false;
|
||||
|
||||
if (isdown)
|
||||
{
|
||||
printf ("recursive shutdown\n");
|
||||
return;
|
||||
}
|
||||
isdown = true;
|
||||
|
||||
// keep Con_Printf from trying to update the screen
|
||||
scr_disabled_for_loading = true;
|
||||
|
||||
Host_WriteConfiguration ();
|
||||
|
||||
NET_Shutdown ();
|
||||
|
||||
if (cls.state != ca_dedicated)
|
||||
{
|
||||
if (con_initialized)
|
||||
History_Shutdown ();
|
||||
BGM_Shutdown();
|
||||
CDAudio_Shutdown ();
|
||||
S_Shutdown ();
|
||||
IN_Shutdown ();
|
||||
VID_Shutdown();
|
||||
}
|
||||
|
||||
LOG_Close ();
|
||||
|
||||
LOC_Shutdown ();
|
||||
}
|
||||
+2364
File diff suppressed because it is too large
Load Diff
+640
@@ -0,0 +1,640 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
//image.c -- image loading
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#define STB_IMAGE_WRITE_STATIC
|
||||
#include "stb_image_write.hpp"
|
||||
|
||||
#define LODEPNG_NO_COMPILE_DECODER
|
||||
#define LODEPNG_NO_COMPILE_CPP
|
||||
#define LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
|
||||
#define LODEPNG_NO_COMPILE_ERROR_TEXT
|
||||
#include "lodepng.hpp"
|
||||
#include "lodepng.cpp"
|
||||
|
||||
static char loadfilename[MAX_OSPATH]; //file scope so that error messages can use it
|
||||
|
||||
typedef struct stdio_buffer_s {
|
||||
FILE *f;
|
||||
unsigned char buffer[1024];
|
||||
int size;
|
||||
int pos;
|
||||
} stdio_buffer_t;
|
||||
|
||||
static stdio_buffer_t *Buf_Alloc(FILE *f)
|
||||
{
|
||||
stdio_buffer_t *buf = (stdio_buffer_t *) calloc(1, sizeof(stdio_buffer_t));
|
||||
buf->f = f;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void Buf_Free(stdio_buffer_t *buf)
|
||||
{
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static inline int Buf_GetC(stdio_buffer_t *buf)
|
||||
{
|
||||
if (buf->pos >= buf->size)
|
||||
{
|
||||
buf->size = fread(buf->buffer, 1, sizeof(buf->buffer), buf->f);
|
||||
buf->pos = 0;
|
||||
|
||||
if (buf->size == 0)
|
||||
return EOF;
|
||||
}
|
||||
|
||||
return buf->buffer[buf->pos++];
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Image_LoadImage
|
||||
|
||||
returns a pointer to hunk allocated RGBA data
|
||||
|
||||
TODO: search order: tga png jpg pcx lmp
|
||||
============
|
||||
*/
|
||||
byte *Image_LoadImage (const char *name, int *width, int *height)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
q_snprintf (loadfilename, sizeof(loadfilename), "%s.tga", name);
|
||||
COM_FOpenFile (loadfilename, &f, NULL);
|
||||
if (f)
|
||||
return Image_LoadTGA (f, width, height);
|
||||
|
||||
q_snprintf (loadfilename, sizeof(loadfilename), "%s.pcx", name);
|
||||
COM_FOpenFile (loadfilename, &f, NULL);
|
||||
if (f)
|
||||
return Image_LoadPCX (f, width, height);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// TGA
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
typedef struct targaheader_s {
|
||||
unsigned char id_length, colormap_type, image_type;
|
||||
unsigned short colormap_index, colormap_length;
|
||||
unsigned char colormap_size;
|
||||
unsigned short x_origin, y_origin, width, height;
|
||||
unsigned char pixel_size, attributes;
|
||||
} targaheader_t;
|
||||
|
||||
#define TARGAHEADERSIZE 18 /* size on disk */
|
||||
|
||||
int fgetLittleShort (FILE *f)
|
||||
{
|
||||
byte b1, b2;
|
||||
|
||||
b1 = fgetc(f);
|
||||
b2 = fgetc(f);
|
||||
|
||||
return (short)(b1 + b2*256);
|
||||
}
|
||||
|
||||
int fgetLittleLong (FILE *f)
|
||||
{
|
||||
byte b1, b2, b3, b4;
|
||||
|
||||
b1 = fgetc(f);
|
||||
b2 = fgetc(f);
|
||||
b3 = fgetc(f);
|
||||
b4 = fgetc(f);
|
||||
|
||||
return b1 + (b2<<8) + (b3<<16) + (b4<<24);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Image_WriteTGA -- writes RGB or RGBA data to a TGA file
|
||||
|
||||
returns true if successful
|
||||
|
||||
TODO: support BGRA and BGR formats (since opengl can return them, and we don't have to swap)
|
||||
============
|
||||
*/
|
||||
qboolean Image_WriteTGA (const char *name, byte *data, int width, int height, int bpp, qboolean upsidedown)
|
||||
{
|
||||
int handle, i, size, temp, bytes;
|
||||
char pathname[MAX_OSPATH];
|
||||
byte header[TARGAHEADERSIZE];
|
||||
|
||||
Sys_mkdir (com_gamedir); //if we've switched to a nonexistant gamedir, create it now so we don't crash
|
||||
q_snprintf (pathname, sizeof(pathname), "%s/%s", com_gamedir, name);
|
||||
handle = Sys_FileOpenWrite (pathname);
|
||||
if (handle == -1)
|
||||
return false;
|
||||
|
||||
Q_memset (header, 0, TARGAHEADERSIZE);
|
||||
header[2] = 2; // uncompressed type
|
||||
header[12] = width&255;
|
||||
header[13] = width>>8;
|
||||
header[14] = height&255;
|
||||
header[15] = height>>8;
|
||||
header[16] = bpp; // pixel size
|
||||
if (upsidedown)
|
||||
header[17] = 0x20; //upside-down attribute
|
||||
|
||||
// swap red and blue bytes
|
||||
bytes = bpp/8;
|
||||
size = width*height*bytes;
|
||||
for (i=0; i<size; i+=bytes)
|
||||
{
|
||||
temp = data[i];
|
||||
data[i] = data[i+2];
|
||||
data[i+2] = temp;
|
||||
}
|
||||
|
||||
Sys_FileWrite (handle, header, TARGAHEADERSIZE);
|
||||
Sys_FileWrite (handle, data, size);
|
||||
Sys_FileClose (handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Image_LoadTGA
|
||||
=============
|
||||
*/
|
||||
byte *Image_LoadTGA (FILE *fin, int *width, int *height)
|
||||
{
|
||||
int columns, rows, numPixels;
|
||||
byte *pixbuf;
|
||||
int row, column;
|
||||
byte *targa_rgba;
|
||||
int realrow; //johnfitz -- fix for upside-down targas
|
||||
qboolean upside_down; //johnfitz -- fix for upside-down targas
|
||||
stdio_buffer_t *buf;
|
||||
targaheader_t targa_header;
|
||||
|
||||
targa_header.id_length = fgetc(fin);
|
||||
targa_header.colormap_type = fgetc(fin);
|
||||
targa_header.image_type = fgetc(fin);
|
||||
|
||||
targa_header.colormap_index = fgetLittleShort(fin);
|
||||
targa_header.colormap_length = fgetLittleShort(fin);
|
||||
targa_header.colormap_size = fgetc(fin);
|
||||
targa_header.x_origin = fgetLittleShort(fin);
|
||||
targa_header.y_origin = fgetLittleShort(fin);
|
||||
targa_header.width = fgetLittleShort(fin);
|
||||
targa_header.height = fgetLittleShort(fin);
|
||||
targa_header.pixel_size = fgetc(fin);
|
||||
targa_header.attributes = fgetc(fin);
|
||||
|
||||
if (targa_header.image_type==1)
|
||||
{
|
||||
if (targa_header.pixel_size != 8 || targa_header.colormap_size != 24 || targa_header.colormap_length > 256)
|
||||
Sys_Error ("Image_LoadTGA: %s has an %ibit palette", loadfilename, targa_header.colormap_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (targa_header.image_type!=2 && targa_header.image_type!=10)
|
||||
Sys_Error ("Image_LoadTGA: %s is not a type 2 or type 10 targa (%i)", loadfilename, targa_header.image_type);
|
||||
|
||||
if (targa_header.colormap_type !=0 || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
|
||||
Sys_Error ("Image_LoadTGA: %s is not a 24bit or 32bit targa", loadfilename);
|
||||
}
|
||||
|
||||
columns = targa_header.width;
|
||||
rows = targa_header.height;
|
||||
numPixels = columns * rows;
|
||||
upside_down = !(targa_header.attributes & 0x20); //johnfitz -- fix for upside-down targas
|
||||
|
||||
targa_rgba = (byte *) Hunk_Alloc (numPixels*4);
|
||||
|
||||
if (targa_header.id_length != 0)
|
||||
fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment
|
||||
|
||||
buf = Buf_Alloc(fin);
|
||||
|
||||
if (targa_header.image_type==1) // Uncompressed, paletted images
|
||||
{
|
||||
byte palette[256*4];
|
||||
int i;
|
||||
//palette data comes first
|
||||
for (i = 0; i < targa_header.colormap_length; i++)
|
||||
{ //this palette data is bgr.
|
||||
palette[i*3+2] = Buf_GetC(buf);
|
||||
palette[i*3+1] = Buf_GetC(buf);
|
||||
palette[i*3+0] = Buf_GetC(buf);
|
||||
palette[i*3+3] = 255;
|
||||
}
|
||||
for (i = targa_header.colormap_length*4; i < sizeof(palette); i++)
|
||||
palette[i] = 0;
|
||||
for(row=rows-1; row>=0; row--)
|
||||
{
|
||||
realrow = upside_down ? row : rows - 1 - row;
|
||||
pixbuf = targa_rgba + realrow*columns*4;
|
||||
|
||||
for(column=0; column<columns; column++)
|
||||
{
|
||||
i = Buf_GetC(buf);
|
||||
*pixbuf++= palette[i*3+0];
|
||||
*pixbuf++= palette[i*3+1];
|
||||
*pixbuf++= palette[i*3+2];
|
||||
*pixbuf++= palette[i*3+3];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (targa_header.image_type==2) // Uncompressed, RGB images
|
||||
{
|
||||
for(row=rows-1; row>=0; row--)
|
||||
{
|
||||
//johnfitz -- fix for upside-down targas
|
||||
realrow = upside_down ? row : rows - 1 - row;
|
||||
pixbuf = targa_rgba + realrow*columns*4;
|
||||
//johnfitz
|
||||
for(column=0; column<columns; column++)
|
||||
{
|
||||
unsigned char red,green,blue,alphabyte;
|
||||
switch (targa_header.pixel_size)
|
||||
{
|
||||
case 24:
|
||||
blue = Buf_GetC(buf);
|
||||
green = Buf_GetC(buf);
|
||||
red = Buf_GetC(buf);
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = 255;
|
||||
break;
|
||||
case 32:
|
||||
blue = Buf_GetC(buf);
|
||||
green = Buf_GetC(buf);
|
||||
red = Buf_GetC(buf);
|
||||
alphabyte = Buf_GetC(buf);
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alphabyte;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (targa_header.image_type==10) // Runlength encoded RGB images
|
||||
{
|
||||
unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
|
||||
for(row=rows-1; row>=0; row--)
|
||||
{
|
||||
//johnfitz -- fix for upside-down targas
|
||||
realrow = upside_down ? row : rows - 1 - row;
|
||||
pixbuf = targa_rgba + realrow*columns*4;
|
||||
//johnfitz
|
||||
for(column=0; column<columns; )
|
||||
{
|
||||
packetHeader=Buf_GetC(buf);
|
||||
packetSize = 1 + (packetHeader & 0x7f);
|
||||
if (packetHeader & 0x80) // run-length packet
|
||||
{
|
||||
switch (targa_header.pixel_size)
|
||||
{
|
||||
case 24:
|
||||
blue = Buf_GetC(buf);
|
||||
green = Buf_GetC(buf);
|
||||
red = Buf_GetC(buf);
|
||||
alphabyte = 255;
|
||||
break;
|
||||
case 32:
|
||||
blue = Buf_GetC(buf);
|
||||
green = Buf_GetC(buf);
|
||||
red = Buf_GetC(buf);
|
||||
alphabyte = Buf_GetC(buf);
|
||||
break;
|
||||
default: /* avoid compiler warnings */
|
||||
blue = red = green = alphabyte = 0;
|
||||
}
|
||||
|
||||
for(j=0;j<packetSize;j++)
|
||||
{
|
||||
*pixbuf++=red;
|
||||
*pixbuf++=green;
|
||||
*pixbuf++=blue;
|
||||
*pixbuf++=alphabyte;
|
||||
column++;
|
||||
if (column==columns) // run spans across rows
|
||||
{
|
||||
column=0;
|
||||
if (row>0)
|
||||
row--;
|
||||
else
|
||||
goto breakOut;
|
||||
//johnfitz -- fix for upside-down targas
|
||||
realrow = upside_down ? row : rows - 1 - row;
|
||||
pixbuf = targa_rgba + realrow*columns*4;
|
||||
//johnfitz
|
||||
}
|
||||
}
|
||||
}
|
||||
else // non run-length packet
|
||||
{
|
||||
for(j=0;j<packetSize;j++)
|
||||
{
|
||||
switch (targa_header.pixel_size)
|
||||
{
|
||||
case 24:
|
||||
blue = Buf_GetC(buf);
|
||||
green = Buf_GetC(buf);
|
||||
red = Buf_GetC(buf);
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = 255;
|
||||
break;
|
||||
case 32:
|
||||
blue = Buf_GetC(buf);
|
||||
green = Buf_GetC(buf);
|
||||
red = Buf_GetC(buf);
|
||||
alphabyte = Buf_GetC(buf);
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alphabyte;
|
||||
break;
|
||||
default: /* avoid compiler warnings */
|
||||
blue = red = green = alphabyte = 0;
|
||||
}
|
||||
column++;
|
||||
if (column==columns) // pixel packet run spans across rows
|
||||
{
|
||||
column=0;
|
||||
if (row>0)
|
||||
row--;
|
||||
else
|
||||
goto breakOut;
|
||||
//johnfitz -- fix for upside-down targas
|
||||
realrow = upside_down ? row : rows - 1 - row;
|
||||
pixbuf = targa_rgba + realrow*columns*4;
|
||||
//johnfitz
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
breakOut:;
|
||||
}
|
||||
}
|
||||
|
||||
Buf_Free(buf);
|
||||
fclose(fin);
|
||||
|
||||
*width = (int)(targa_header.width);
|
||||
*height = (int)(targa_header.height);
|
||||
return targa_rgba;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// PCX
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char signature;
|
||||
char version;
|
||||
char encoding;
|
||||
char bits_per_pixel;
|
||||
unsigned short xmin,ymin,xmax,ymax;
|
||||
unsigned short hdpi,vdpi;
|
||||
byte colortable[48];
|
||||
char reserved;
|
||||
char color_planes;
|
||||
unsigned short bytes_per_line;
|
||||
unsigned short palette_type;
|
||||
char filler[58];
|
||||
} pcxheader_t;
|
||||
|
||||
/*
|
||||
============
|
||||
Image_LoadPCX
|
||||
============
|
||||
*/
|
||||
byte *Image_LoadPCX (FILE *f, int *width, int *height)
|
||||
{
|
||||
pcxheader_t pcx;
|
||||
int x, y, w, h, readbyte, runlength, start;
|
||||
byte *p, *data;
|
||||
byte palette[768];
|
||||
stdio_buffer_t *buf;
|
||||
|
||||
start = ftell (f); //save start of file (since we might be inside a pak file, SEEK_SET might not be the start of the pcx)
|
||||
|
||||
if (!fread(&pcx, sizeof(pcx), 1, f))
|
||||
Sys_Error ("Failed reading header from '%s'", loadfilename);
|
||||
pcx.xmin = (unsigned short)LittleShort (pcx.xmin);
|
||||
pcx.ymin = (unsigned short)LittleShort (pcx.ymin);
|
||||
pcx.xmax = (unsigned short)LittleShort (pcx.xmax);
|
||||
pcx.ymax = (unsigned short)LittleShort (pcx.ymax);
|
||||
pcx.bytes_per_line = (unsigned short)LittleShort (pcx.bytes_per_line);
|
||||
|
||||
if (pcx.signature != 0x0A)
|
||||
Sys_Error ("'%s' is not a valid PCX file", loadfilename);
|
||||
|
||||
if (pcx.version != 5)
|
||||
Sys_Error ("'%s' is version %i, should be 5", loadfilename, pcx.version);
|
||||
|
||||
if (pcx.encoding != 1 || pcx.bits_per_pixel != 8 || pcx.color_planes != 1)
|
||||
Sys_Error ("'%s' has wrong encoding or bit depth", loadfilename);
|
||||
|
||||
w = pcx.xmax - pcx.xmin + 1;
|
||||
h = pcx.ymax - pcx.ymin + 1;
|
||||
|
||||
data = (byte *) Hunk_Alloc((w*h+1)*4); //+1 to allow reading padding byte on last line
|
||||
|
||||
//load palette
|
||||
fseek (f, start + com_filesize - 768, SEEK_SET);
|
||||
if (!fread (palette, 768, 1, f))
|
||||
Sys_Error ("Failed reading palette from '%s'", loadfilename);
|
||||
|
||||
//back to start of image data
|
||||
fseek (f, start + sizeof(pcx), SEEK_SET);
|
||||
|
||||
buf = Buf_Alloc(f);
|
||||
|
||||
for (y=0; y<h; y++)
|
||||
{
|
||||
p = data + y * w * 4;
|
||||
|
||||
for (x=0; x<(pcx.bytes_per_line); ) //read the extra padding byte if necessary
|
||||
{
|
||||
readbyte = Buf_GetC(buf);
|
||||
|
||||
if(readbyte >= 0xC0)
|
||||
{
|
||||
runlength = readbyte & 0x3F;
|
||||
readbyte = Buf_GetC(buf);
|
||||
}
|
||||
else
|
||||
runlength = 1;
|
||||
|
||||
while(runlength--)
|
||||
{
|
||||
p[0] = palette[readbyte*3];
|
||||
p[1] = palette[readbyte*3+1];
|
||||
p[2] = palette[readbyte*3+2];
|
||||
p[3] = 255;
|
||||
p += 4;
|
||||
x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Buf_Free(buf);
|
||||
fclose(f);
|
||||
|
||||
*width = w;
|
||||
*height = h;
|
||||
return data;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// STB_IMAGE_WRITE
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
static byte *CopyFlipped(const byte *data, int width, int height, int bpp)
|
||||
{
|
||||
int y, rowsize;
|
||||
byte *flipped;
|
||||
|
||||
rowsize = width * (bpp / 8);
|
||||
flipped = (byte *) malloc(height * rowsize);
|
||||
if (!flipped)
|
||||
return NULL;
|
||||
|
||||
for (y=0; y<height; y++)
|
||||
{
|
||||
memcpy(&flipped[y * rowsize], &data[(height - 1 - y) * rowsize], rowsize);
|
||||
}
|
||||
return flipped;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Image_WriteJPG -- writes using stb_image_write
|
||||
|
||||
returns true if successful
|
||||
============
|
||||
*/
|
||||
qboolean Image_WriteJPG (const char *name, byte *data, int width, int height, int bpp, int quality, qboolean upsidedown)
|
||||
{
|
||||
unsigned error;
|
||||
char pathname[MAX_OSPATH];
|
||||
byte *flipped;
|
||||
int bytes_per_pixel;
|
||||
|
||||
if (!(bpp == 32 || bpp == 24))
|
||||
Sys_Error ("bpp not 24 or 32");
|
||||
|
||||
bytes_per_pixel = bpp / 8;
|
||||
|
||||
Sys_mkdir (com_gamedir); //if we've switched to a nonexistant gamedir, create it now so we don't crash
|
||||
q_snprintf (pathname, sizeof(pathname), "%s/%s", com_gamedir, name);
|
||||
|
||||
if (!upsidedown)
|
||||
{
|
||||
flipped = CopyFlipped (data, width, height, bpp);
|
||||
if (!flipped)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
flipped = data;
|
||||
|
||||
error = stbi_write_jpg (pathname, width, height, bytes_per_pixel, flipped, quality);
|
||||
if (!upsidedown)
|
||||
free (flipped);
|
||||
|
||||
return (error != 0);
|
||||
}
|
||||
|
||||
qboolean Image_WritePNG (const char *name, byte *data, int width, int height, int bpp, qboolean upsidedown)
|
||||
{
|
||||
unsigned error;
|
||||
char pathname[MAX_OSPATH];
|
||||
byte *flipped;
|
||||
unsigned char *filters;
|
||||
unsigned char *png;
|
||||
size_t pngsize;
|
||||
LodePNGState state;
|
||||
|
||||
if (!(bpp == 32 || bpp == 24))
|
||||
Sys_Error("bpp not 24 or 32");
|
||||
|
||||
Sys_mkdir (com_gamedir); //if we've switched to a nonexistant gamedir, create it now so we don't crash
|
||||
q_snprintf (pathname, sizeof(pathname), "%s/%s", com_gamedir, name);
|
||||
|
||||
flipped = (!upsidedown)? CopyFlipped (data, width, height, bpp) : data;
|
||||
filters = (unsigned char *) malloc (height);
|
||||
if (!filters || !flipped)
|
||||
{
|
||||
if (!upsidedown)
|
||||
free (flipped);
|
||||
free (filters);
|
||||
return false;
|
||||
}
|
||||
|
||||
// set some options for faster compression
|
||||
lodepng_state_init(&state);
|
||||
state.encoder.zlibsettings.use_lz77 = 0;
|
||||
state.encoder.auto_convert = 0;
|
||||
state.encoder.filter_strategy = LFS_PREDEFINED;
|
||||
memset(filters, 1, height); //use filter 1; see https://www.w3.org/TR/PNG-Filters.html
|
||||
state.encoder.predefined_filters = filters;
|
||||
|
||||
if (bpp == 24)
|
||||
{
|
||||
state.info_raw.colortype = LCT_RGB;
|
||||
state.info_png.color.colortype = LCT_RGB;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.info_raw.colortype = LCT_RGBA;
|
||||
state.info_png.color.colortype = LCT_RGBA;
|
||||
}
|
||||
|
||||
error = lodepng_encode (&png, &pngsize, flipped, width, height, &state);
|
||||
if (error == 0) lodepng_save_file (png, pngsize, pathname);
|
||||
#ifdef LODEPNG_COMPILE_ERROR_TEXT
|
||||
else Con_Printf("WritePNG: %s\n", lodepng_error_text (error));
|
||||
#endif
|
||||
|
||||
lodepng_state_cleanup (&state);
|
||||
lodepng_free (png); /* png was allocated by lodepng */
|
||||
free (filters);
|
||||
if (!upsidedown) {
|
||||
free (flipped);
|
||||
}
|
||||
|
||||
return (error == 0);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 GL_IMAGE_H
|
||||
#define GL_IMAGE_H
|
||||
|
||||
//image.h -- image reading / writing
|
||||
|
||||
//be sure to free the hunk after using these loading functions
|
||||
byte *Image_LoadTGA (FILE *f, int *width, int *height);
|
||||
byte *Image_LoadPCX (FILE *f, int *width, int *height);
|
||||
byte *Image_LoadImage (const char *name, int *width, int *height);
|
||||
|
||||
qboolean Image_WriteTGA (const char *name, byte *data, int width, int height, int bpp, qboolean upsidedown);
|
||||
qboolean Image_WritePNG (const char *name, byte *data, int width, int height, int bpp, qboolean upsidedown);
|
||||
qboolean Image_WriteJPG (const char *name, byte *data, int width, int height, int bpp, int quality, qboolean upsidedown);
|
||||
|
||||
#endif /* GL_IMAGE_H */
|
||||
|
||||
+1160
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 QUAKE_INPUT_H
|
||||
#define QUAKE_INPUT_H
|
||||
|
||||
// input.h -- external (non-keyboard) input devices
|
||||
|
||||
void IN_Init (void);
|
||||
|
||||
void IN_Shutdown (void);
|
||||
|
||||
void IN_Commands (void);
|
||||
// oportunity for devices to stick commands on the script buffer
|
||||
|
||||
// mouse moved by dx and dy pixels
|
||||
void IN_MouseMotion(int dx, int dy);
|
||||
|
||||
|
||||
void IN_SendKeyEvents (void);
|
||||
// used as a callback for Sys_SendKeyEvents() by some drivers
|
||||
|
||||
void IN_UpdateInputMode (void);
|
||||
// do stuff if input mode (text/non-text) changes matter to the keyboard driver
|
||||
|
||||
void IN_Move (usercmd_t *cmd);
|
||||
// add additional movement on top of the keyboard move cmd
|
||||
|
||||
void IN_ClearStates (void);
|
||||
// restores all button and position states to defaults
|
||||
|
||||
// called when the app becomes active
|
||||
void IN_Activate (void);
|
||||
|
||||
// called when the app becomes inactive
|
||||
void IN_Deactivate (qboolean free_cursor);
|
||||
|
||||
#endif
|
||||
+1239
File diff suppressed because it is too large
Load Diff
+201
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 _QUAKE_KEYS_H
|
||||
#define _QUAKE_KEYS_H
|
||||
|
||||
//
|
||||
// these are the key numbers that should be passed to Key_Event
|
||||
//
|
||||
#define K_TAB 9
|
||||
#define K_ENTER 13
|
||||
#define K_ESCAPE 27
|
||||
#define K_SPACE 32
|
||||
|
||||
// normal keys should be passed as lowercased ascii
|
||||
|
||||
#define K_BACKSPACE 127
|
||||
#define K_UPARROW 128
|
||||
#define K_DOWNARROW 129
|
||||
#define K_LEFTARROW 130
|
||||
#define K_RIGHTARROW 131
|
||||
|
||||
#define K_ALT 132
|
||||
#define K_CTRL 133
|
||||
#define K_SHIFT 134
|
||||
#define K_F1 135
|
||||
#define K_F2 136
|
||||
#define K_F3 137
|
||||
#define K_F4 138
|
||||
#define K_F5 139
|
||||
#define K_F6 140
|
||||
#define K_F7 141
|
||||
#define K_F8 142
|
||||
#define K_F9 143
|
||||
#define K_F10 144
|
||||
#define K_F11 145
|
||||
#define K_F12 146
|
||||
#define K_INS 147
|
||||
#define K_DEL 148
|
||||
#define K_PGDN 149
|
||||
#define K_PGUP 150
|
||||
#define K_HOME 151
|
||||
#define K_END 152
|
||||
|
||||
#define K_KP_NUMLOCK 153
|
||||
#define K_KP_SLASH 154
|
||||
#define K_KP_STAR 155
|
||||
#define K_KP_MINUS 156
|
||||
#define K_KP_HOME 157
|
||||
#define K_KP_UPARROW 158
|
||||
#define K_KP_PGUP 159
|
||||
#define K_KP_PLUS 160
|
||||
#define K_KP_LEFTARROW 161
|
||||
#define K_KP_5 162
|
||||
#define K_KP_RIGHTARROW 163
|
||||
#define K_KP_END 164
|
||||
#define K_KP_DOWNARROW 165
|
||||
#define K_KP_PGDN 166
|
||||
#define K_KP_ENTER 167
|
||||
#define K_KP_INS 168
|
||||
#define K_KP_DEL 169
|
||||
|
||||
#define K_COMMAND 170
|
||||
|
||||
#define K_PAUSE 255
|
||||
|
||||
//
|
||||
// mouse buttons generate virtual keys
|
||||
//
|
||||
#define K_MOUSE1 200
|
||||
#define K_MOUSE2 201
|
||||
#define K_MOUSE3 202
|
||||
|
||||
//
|
||||
// joystick buttons
|
||||
//
|
||||
#define K_JOY1 203
|
||||
#define K_JOY2 204
|
||||
#define K_JOY3 205
|
||||
#define K_JOY4 206
|
||||
// aux keys are for multi-buttoned joysticks to generate so they can use
|
||||
// the normal binding process
|
||||
// aux29-32: reserved for the HAT (POV) switch motion
|
||||
#define K_AUX1 207
|
||||
#define K_AUX2 208
|
||||
#define K_AUX3 209
|
||||
#define K_AUX4 210
|
||||
#define K_AUX5 211
|
||||
#define K_AUX6 212
|
||||
#define K_AUX7 213
|
||||
#define K_AUX8 214
|
||||
#define K_AUX9 215
|
||||
#define K_AUX10 216
|
||||
#define K_AUX11 217
|
||||
#define K_AUX12 218
|
||||
#define K_AUX13 219
|
||||
#define K_AUX14 220
|
||||
#define K_AUX15 221
|
||||
#define K_AUX16 222
|
||||
#define K_AUX17 223
|
||||
#define K_AUX18 224
|
||||
#define K_AUX19 225
|
||||
#define K_AUX20 226
|
||||
#define K_AUX21 227
|
||||
#define K_AUX22 228
|
||||
#define K_AUX23 229
|
||||
#define K_AUX24 230
|
||||
#define K_AUX25 231
|
||||
#define K_AUX26 232
|
||||
#define K_AUX27 233
|
||||
#define K_AUX28 234
|
||||
#define K_AUX29 235
|
||||
#define K_AUX30 236
|
||||
#define K_AUX31 237
|
||||
#define K_AUX32 238
|
||||
|
||||
// JACK: Intellimouse(c) Mouse Wheel Support
|
||||
|
||||
#define K_MWHEELUP 239
|
||||
#define K_MWHEELDOWN 240
|
||||
|
||||
// thumb buttons
|
||||
#define K_MOUSE4 241
|
||||
#define K_MOUSE5 242
|
||||
|
||||
// SDL2 game controller keys
|
||||
#define K_LTHUMB 243
|
||||
#define K_RTHUMB 244
|
||||
#define K_LSHOULDER 245
|
||||
#define K_RSHOULDER 246
|
||||
#define K_ABUTTON 247
|
||||
#define K_BBUTTON 248
|
||||
#define K_XBUTTON 249
|
||||
#define K_YBUTTON 250
|
||||
#define K_LTRIGGER 251
|
||||
#define K_RTRIGGER 252
|
||||
|
||||
#define MAX_KEYS 256
|
||||
|
||||
#define MAXCMDLINE 256
|
||||
|
||||
typedef enum {key_game, key_console, key_message, key_menu} keydest_t;
|
||||
|
||||
extern keydest_t key_dest;
|
||||
extern char *keybindings[MAX_KEYS];
|
||||
|
||||
#define CMDLINES 64
|
||||
|
||||
extern char key_lines[CMDLINES][MAXCMDLINE];
|
||||
extern int edit_line;
|
||||
extern int key_linepos;
|
||||
extern int key_insert;
|
||||
extern double key_blinktime;
|
||||
|
||||
extern qboolean chat_team;
|
||||
|
||||
void Key_Init (void);
|
||||
void Key_ClearStates (void);
|
||||
void Key_UpdateForDest (void);
|
||||
|
||||
void Key_BeginInputGrab (void);
|
||||
void Key_EndInputGrab (void);
|
||||
void Key_GetGrabbedInput (int *lastkey, int *lastchar);
|
||||
|
||||
void Key_Event (int key, qboolean down);
|
||||
void Key_EventWithKeycode (int key, qboolean down, int keycode);
|
||||
void Char_Event (int key);
|
||||
qboolean Key_TextEntry (void);
|
||||
|
||||
void Key_SetBinding (int keynum, const char *binding);
|
||||
const char *Key_KeynumToString (int keynum);
|
||||
void Key_WriteBindings (FILE *f);
|
||||
|
||||
void Key_EndChat (void);
|
||||
const char *Key_GetChatBuffer (void);
|
||||
int Key_GetChatMsgLen (void);
|
||||
|
||||
void History_Init (void);
|
||||
void History_Shutdown (void);
|
||||
|
||||
#endif /* _QUAKE_KEYS_H */
|
||||
|
||||
+6665
File diff suppressed because it is too large
Load Diff
+2085
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2005 John Fitzgibbons and others
|
||||
Copyright (C) 2007-2008 Kristian Duske
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include "quakedef.hpp"
|
||||
#if defined(SDL_FRAMEWORK) || defined(NO_SDL_CONFIG)
|
||||
#if defined(USE_SDL2)
|
||||
#include <SDL2/SDL.h>
|
||||
#else
|
||||
#include <SDL/SDL.h>
|
||||
#endif
|
||||
#else
|
||||
#include "SDL.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
static void Sys_AtExit (void)
|
||||
{
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
static void Sys_InitSDL (void)
|
||||
{
|
||||
#if defined(USE_SDL2)
|
||||
SDL_version v;
|
||||
SDL_version *sdl_version = &v;
|
||||
SDL_GetVersion(&v);
|
||||
#else
|
||||
const SDL_version *sdl_version = SDL_Linked_Version();
|
||||
#endif
|
||||
|
||||
Sys_Printf("Found SDL version %i.%i.%i\n",sdl_version->major,sdl_version->minor,sdl_version->patch);
|
||||
|
||||
if (SDL_Init(0) < 0) {
|
||||
Sys_Error("Couldn't init SDL: %s", SDL_GetError());
|
||||
}
|
||||
atexit(Sys_AtExit);
|
||||
}
|
||||
|
||||
#define DEFAULT_MEMORY (256 * 1024 * 1024) // ericw -- was 72MB (64-bit) / 64MB (32-bit)
|
||||
|
||||
static quakeparms_t parms;
|
||||
|
||||
// On OS X we call SDL_main from the launcher, but SDL2 doesn't redefine main
|
||||
// as SDL_main on OS X anymore, so we do it ourselves.
|
||||
#if defined(USE_SDL2) && defined(__APPLE__)
|
||||
#define main SDL_main
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int t;
|
||||
double time, oldtime, newtime;
|
||||
|
||||
host_parms = &parms;
|
||||
parms.basedir = ".";
|
||||
|
||||
parms.argc = argc;
|
||||
parms.argv = argv;
|
||||
|
||||
parms.errstate = 0;
|
||||
|
||||
COM_InitArgv(parms.argc, parms.argv);
|
||||
|
||||
isDedicated = (COM_CheckParm("-dedicated") != 0);
|
||||
|
||||
Sys_InitSDL ();
|
||||
|
||||
Sys_Init();
|
||||
|
||||
Sys_Printf("Initializing QuakeSpasm v%s\n", QUAKESPASM_VER_STRING);
|
||||
|
||||
parms.memsize = DEFAULT_MEMORY;
|
||||
if (COM_CheckParm("-heapsize"))
|
||||
{
|
||||
t = COM_CheckParm("-heapsize") + 1;
|
||||
if (t < com_argc)
|
||||
parms.memsize = Q_atoi(com_argv[t]) * 1024;
|
||||
}
|
||||
|
||||
parms.membase = malloc (parms.memsize);
|
||||
|
||||
if (!parms.membase)
|
||||
Sys_Error ("Not enough memory free; check disk space\n");
|
||||
|
||||
Sys_Printf("Host_Init\n");
|
||||
Host_Init();
|
||||
|
||||
oldtime = Sys_DoubleTime();
|
||||
if (isDedicated)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
newtime = Sys_DoubleTime ();
|
||||
time = newtime - oldtime;
|
||||
|
||||
while (time < sys_ticrate.value )
|
||||
{
|
||||
SDL_Delay(1);
|
||||
newtime = Sys_DoubleTime ();
|
||||
time = newtime - oldtime;
|
||||
}
|
||||
|
||||
Host_Frame (time);
|
||||
oldtime = newtime;
|
||||
}
|
||||
}
|
||||
else
|
||||
while (1)
|
||||
{
|
||||
/* If we have no input focus at all, sleep a bit */
|
||||
if (!VID_HasMouseOrInputFocus() || cl.paused)
|
||||
{
|
||||
SDL_Delay(16);
|
||||
}
|
||||
/* If we're minimised, sleep a bit more */
|
||||
if (VID_IsMinimized())
|
||||
{
|
||||
scr_skipupdate = 1;
|
||||
SDL_Delay(32);
|
||||
}
|
||||
else
|
||||
{
|
||||
scr_skipupdate = 0;
|
||||
}
|
||||
newtime = Sys_DoubleTime ();
|
||||
time = newtime - oldtime;
|
||||
|
||||
Host_Frame (time);
|
||||
|
||||
if (time < sys_throttle.value && !cls.timedemo)
|
||||
SDL_Delay(1);
|
||||
|
||||
oldtime = newtime;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2007-2008 Kristian Duske
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
// mathlib.c -- math primitives
|
||||
|
||||
#include "quakedef.hpp"
|
||||
|
||||
vec3_t vec3_origin = {0,0,0};
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
|
||||
void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
|
||||
{
|
||||
float d;
|
||||
vec3_t n;
|
||||
float inv_denom;
|
||||
|
||||
inv_denom = 1.0F / DotProduct( normal, normal );
|
||||
|
||||
d = DotProduct( normal, p ) * inv_denom;
|
||||
|
||||
n[0] = normal[0] * inv_denom;
|
||||
n[1] = normal[1] * inv_denom;
|
||||
n[2] = normal[2] * inv_denom;
|
||||
|
||||
dst[0] = p[0] - d * n[0];
|
||||
dst[1] = p[1] - d * n[1];
|
||||
dst[2] = p[2] - d * n[2];
|
||||
}
|
||||
|
||||
/*
|
||||
** assumes "src" is normalized
|
||||
*/
|
||||
void PerpendicularVector( vec3_t dst, const vec3_t src )
|
||||
{
|
||||
int pos;
|
||||
int i;
|
||||
float minelem = 1.0F;
|
||||
vec3_t tempvec;
|
||||
|
||||
/*
|
||||
** find the smallest magnitude axially aligned vector
|
||||
*/
|
||||
for ( pos = 0, i = 0; i < 3; i++ )
|
||||
{
|
||||
if ( fabs( src[i] ) < minelem )
|
||||
{
|
||||
pos = i;
|
||||
minelem = fabs( src[i] );
|
||||
}
|
||||
}
|
||||
tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
|
||||
tempvec[pos] = 1.0F;
|
||||
|
||||
/*
|
||||
** project the point onto the plane defined by src
|
||||
*/
|
||||
ProjectPointOnPlane( dst, tempvec, src );
|
||||
|
||||
/*
|
||||
** normalize the result
|
||||
*/
|
||||
VectorNormalize( dst );
|
||||
}
|
||||
|
||||
//johnfitz -- removed RotatePointAroundVector() becuase it's no longer used and my compiler fucked it up anyway
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
|
||||
float anglemod(float a)
|
||||
{
|
||||
#if 0
|
||||
if (a >= 0)
|
||||
a -= 360*(int)(a/360);
|
||||
else
|
||||
a += 360*( 1 + (int)(-a/360) );
|
||||
#endif
|
||||
a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
BoxOnPlaneSide
|
||||
|
||||
Returns 1, 2, or 1 + 2
|
||||
==================
|
||||
*/
|
||||
int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, mplane_t *p)
|
||||
{
|
||||
float dist1, dist2;
|
||||
int xneg, yneg, zneg;
|
||||
int sides;
|
||||
|
||||
#if 0 // this is done by the BOX_ON_PLANE_SIDE macro before calling this
|
||||
// function
|
||||
// fast axial cases
|
||||
if (p->type < 3)
|
||||
{
|
||||
if (p->dist <= emins[p->type])
|
||||
return 1;
|
||||
if (p->dist >= emaxs[p->type])
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
xneg = p->signbits & 1;
|
||||
yneg = (p->signbits >> 1) & 1;
|
||||
zneg = (p->signbits >> 2) & 1;
|
||||
|
||||
dist1 = p->normal[0] * (xneg ? emins : emaxs)[0] +
|
||||
p->normal[1] * (yneg ? emins : emaxs)[1] +
|
||||
p->normal[2] * (zneg ? emins : emaxs)[2];
|
||||
dist2 = p->normal[0] * (xneg ? emaxs : emins)[0] +
|
||||
p->normal[1] * (yneg ? emaxs : emins)[1] +
|
||||
p->normal[2] * (zneg ? emaxs : emins)[2];
|
||||
|
||||
if (p->signbits & ~7)
|
||||
Sys_Error ("BoxOnPlaneSide: Bad signbits");
|
||||
|
||||
#if 0
|
||||
int i;
|
||||
vec3_t corners[2];
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
if (plane->normal[i] < 0)
|
||||
{
|
||||
corners[0][i] = emins[i];
|
||||
corners[1][i] = emaxs[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
corners[1][i] = emins[i];
|
||||
corners[0][i] = emaxs[i];
|
||||
}
|
||||
}
|
||||
dist = DotProduct (plane->normal, corners[0]) - plane->dist;
|
||||
dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
|
||||
sides = 0;
|
||||
if (dist1 >= 0)
|
||||
sides = 1;
|
||||
if (dist2 < 0)
|
||||
sides |= 2;
|
||||
#endif
|
||||
|
||||
sides = 0;
|
||||
if (dist1 >= p->dist)
|
||||
sides = 1;
|
||||
if (dist2 < p->dist)
|
||||
sides |= 2;
|
||||
|
||||
#ifdef PARANOID
|
||||
if (sides == 0)
|
||||
Sys_Error ("BoxOnPlaneSide: sides==0");
|
||||
#endif
|
||||
|
||||
return sides;
|
||||
}
|
||||
|
||||
//johnfitz -- the opposite of AngleVectors. this takes forward and generates pitch yaw roll
|
||||
//TODO: take right and up vectors to properly set yaw and roll
|
||||
void VectorAngles (const vec3_t forward, vec3_t angles)
|
||||
{
|
||||
vec3_t temp;
|
||||
|
||||
temp[0] = forward[0];
|
||||
temp[1] = forward[1];
|
||||
temp[2] = 0;
|
||||
angles[PITCH] = -atan2(forward[2], VectorLength(temp)) / M_PI_DIV_180;
|
||||
angles[YAW] = atan2(forward[1], forward[0]) / M_PI_DIV_180;
|
||||
angles[ROLL] = 0;
|
||||
}
|
||||
|
||||
void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
|
||||
{
|
||||
float angle;
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
angle = angles[YAW] * (M_PI*2 / 360);
|
||||
sy = sin(angle);
|
||||
cy = cos(angle);
|
||||
angle = angles[PITCH] * (M_PI*2 / 360);
|
||||
sp = sin(angle);
|
||||
cp = cos(angle);
|
||||
angle = angles[ROLL] * (M_PI*2 / 360);
|
||||
sr = sin(angle);
|
||||
cr = cos(angle);
|
||||
|
||||
forward[0] = cp*cy;
|
||||
forward[1] = cp*sy;
|
||||
forward[2] = -sp;
|
||||
right[0] = (-1*sr*sp*cy+-1*cr*-sy);
|
||||
right[1] = (-1*sr*sp*sy+-1*cr*cy);
|
||||
right[2] = -1*sr*cp;
|
||||
up[0] = (cr*sp*cy+-sr*-sy);
|
||||
up[1] = (cr*sp*sy+-sr*cy);
|
||||
up[2] = cr*cp;
|
||||
}
|
||||
|
||||
int VectorCompare (vec3_t v1, vec3_t v2)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
if (v1[i] != v2[i])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
|
||||
{
|
||||
vecc[0] = veca[0] + scale*vecb[0];
|
||||
vecc[1] = veca[1] + scale*vecb[1];
|
||||
vecc[2] = veca[2] + scale*vecb[2];
|
||||
}
|
||||
|
||||
|
||||
vec_t _DotProduct (vec3_t v1, vec3_t v2)
|
||||
{
|
||||
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
|
||||
}
|
||||
|
||||
void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
|
||||
{
|
||||
out[0] = veca[0]-vecb[0];
|
||||
out[1] = veca[1]-vecb[1];
|
||||
out[2] = veca[2]-vecb[2];
|
||||
}
|
||||
|
||||
void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
|
||||
{
|
||||
out[0] = veca[0]+vecb[0];
|
||||
out[1] = veca[1]+vecb[1];
|
||||
out[2] = veca[2]+vecb[2];
|
||||
}
|
||||
|
||||
void _VectorCopy (vec3_t in, vec3_t out)
|
||||
{
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
}
|
||||
|
||||
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
|
||||
{
|
||||
cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
||||
cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
|
||||
cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
|
||||
}
|
||||
|
||||
vec_t VectorLength(vec3_t v)
|
||||
{
|
||||
return sqrt(DotProduct(v,v));
|
||||
}
|
||||
|
||||
float VectorNormalize (vec3_t v)
|
||||
{
|
||||
float length, ilength;
|
||||
|
||||
length = sqrt(DotProduct(v,v));
|
||||
|
||||
if (length)
|
||||
{
|
||||
ilength = 1/length;
|
||||
v[0] *= ilength;
|
||||
v[1] *= ilength;
|
||||
v[2] *= ilength;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void VectorInverse (vec3_t v)
|
||||
{
|
||||
v[0] = -v[0];
|
||||
v[1] = -v[1];
|
||||
v[2] = -v[2];
|
||||
}
|
||||
|
||||
void VectorScale (vec3_t in, vec_t scale, vec3_t out)
|
||||
{
|
||||
out[0] = in[0]*scale;
|
||||
out[1] = in[1]*scale;
|
||||
out[2] = in[2]*scale;
|
||||
}
|
||||
|
||||
|
||||
int Q_log2(int val)
|
||||
{
|
||||
int answer=0;
|
||||
while (val>>=1)
|
||||
answer++;
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_ConcatRotations
|
||||
================
|
||||
*/
|
||||
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
|
||||
{
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
|
||||
in1[0][2] * in2[2][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
|
||||
in1[0][2] * in2[2][1];
|
||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
|
||||
in1[0][2] * in2[2][2];
|
||||
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
|
||||
in1[1][2] * in2[2][0];
|
||||
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
|
||||
in1[1][2] * in2[2][1];
|
||||
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
|
||||
in1[1][2] * in2[2][2];
|
||||
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
|
||||
in1[2][2] * in2[2][0];
|
||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
|
||||
in1[2][2] * in2[2][1];
|
||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
|
||||
in1[2][2] * in2[2][2];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
R_ConcatTransforms
|
||||
================
|
||||
*/
|
||||
void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
|
||||
{
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
|
||||
in1[0][2] * in2[2][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
|
||||
in1[0][2] * in2[2][1];
|
||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
|
||||
in1[0][2] * in2[2][2];
|
||||
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
|
||||
in1[0][2] * in2[2][3] + in1[0][3];
|
||||
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
|
||||
in1[1][2] * in2[2][0];
|
||||
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
|
||||
in1[1][2] * in2[2][1];
|
||||
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
|
||||
in1[1][2] * in2[2][2];
|
||||
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
|
||||
in1[1][2] * in2[2][3] + in1[1][3];
|
||||
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
|
||||
in1[2][2] * in2[2][0];
|
||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
|
||||
in1[2][2] * in2[2][1];
|
||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
|
||||
in1[2][2] * in2[2][2];
|
||||
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
|
||||
in1[2][2] * in2[2][3] + in1[2][3];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
FloorDivMod
|
||||
|
||||
Returns mathematically correct (floor-based) quotient and remainder for
|
||||
numer and denom, both of which should contain no fractional part. The
|
||||
quotient must fit in 32 bits.
|
||||
====================
|
||||
*/
|
||||
|
||||
void FloorDivMod (double numer, double denom, int *quotient,
|
||||
int *rem)
|
||||
{
|
||||
int q, r;
|
||||
double x;
|
||||
|
||||
#ifndef PARANOID
|
||||
if (denom <= 0.0)
|
||||
Sys_Error ("FloorDivMod: bad denominator %f\n", denom);
|
||||
|
||||
// if ((floor(numer) != numer) || (floor(denom) != denom))
|
||||
// Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
|
||||
// numer, denom);
|
||||
#endif
|
||||
|
||||
if (numer >= 0.0)
|
||||
{
|
||||
|
||||
x = floor(numer / denom);
|
||||
q = (int)x;
|
||||
r = (int)floor(numer - (x * denom));
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// perform operations with positive values, and fix mod to make floor-based
|
||||
//
|
||||
x = floor(-numer / denom);
|
||||
q = -(int)x;
|
||||
r = (int)floor(-numer - (x * denom));
|
||||
if (r != 0)
|
||||
{
|
||||
q--;
|
||||
r = (int)denom - r;
|
||||
}
|
||||
}
|
||||
|
||||
*quotient = q;
|
||||
*rem = r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
GreatestCommonDivisor
|
||||
====================
|
||||
*/
|
||||
int GreatestCommonDivisor (int i1, int i2)
|
||||
{
|
||||
if (i1 > i2)
|
||||
{
|
||||
if (i2 == 0)
|
||||
return (i1);
|
||||
return GreatestCommonDivisor (i2, i1 % i2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i1 == 0)
|
||||
return (i2);
|
||||
return GreatestCommonDivisor (i1, i2 % i1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===================
|
||||
Invert24To16
|
||||
|
||||
Inverts an 8.24 value to a 16.16 value
|
||||
====================
|
||||
*/
|
||||
|
||||
fixed16_t Invert24To16(fixed16_t val)
|
||||
{
|
||||
if (val < 256)
|
||||
return (0xFFFFFFFF);
|
||||
|
||||
return (fixed16_t)
|
||||
(((double)0x10000 * (double)0x1000000 / (double)val) + 0.5);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2007-2008 Kristian Duske
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 __MATHLIB_H
|
||||
#define __MATHLIB_H
|
||||
|
||||
// mathlib.h
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
|
||||
#endif
|
||||
|
||||
#define M_PI_DIV_180 (M_PI / 180.0) //johnfitz
|
||||
#define DEG2RAD(a) ((a) * M_PI_DIV_180)
|
||||
|
||||
struct mplane_s;
|
||||
|
||||
extern vec3_t vec3_origin;
|
||||
|
||||
#define nanmask (255 << 23) /* 7F800000 */
|
||||
#if 0 /* macro is violating strict aliasing rules */
|
||||
#define IS_NAN(x) (((*(int *) (char *) &x) & nanmask) == nanmask)
|
||||
#else
|
||||
static inline int IS_NAN (float x) {
|
||||
union { float f; int i; } num;
|
||||
num.f = x;
|
||||
return ((num.i & nanmask) == nanmask);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define Q_rint(x) ((x) > 0 ? (int)((x) + 0.5) : (int)((x) - 0.5)) //johnfitz -- from joequake
|
||||
|
||||
#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
|
||||
#define DoublePrecisionDotProduct(x,y) ((double)(x)[0]*(y)[0]+(double)(x)[1]*(y)[1]+(double)(x)[2]*(y)[2])
|
||||
#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];}
|
||||
#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];}
|
||||
#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}
|
||||
|
||||
//johnfitz -- courtesy of lordhavoc
|
||||
// QuakeSpasm: To avoid strict aliasing violations, use a float/int union instead of type punning.
|
||||
#define VectorNormalizeFast(_v)\
|
||||
{\
|
||||
union { float f; int i; } _y, _number;\
|
||||
_number.f = DotProduct((_v), (_v));\
|
||||
if (_number.f != 0.0)\
|
||||
{\
|
||||
_y.i = 0x5f3759df - (_number.i >> 1);\
|
||||
_y.f = _y.f * (1.5f - (_number.f * 0.5f * _y.f * _y.f));\
|
||||
VectorScale((_v), _y.f, (_v));\
|
||||
}\
|
||||
}
|
||||
|
||||
void TurnVector (vec3_t out, const vec3_t forward, const vec3_t side, float angle); //johnfitz
|
||||
void VectorAngles (const vec3_t forward, vec3_t angles); //johnfitz
|
||||
|
||||
void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);
|
||||
|
||||
vec_t _DotProduct (vec3_t v1, vec3_t v2);
|
||||
void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out);
|
||||
void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out);
|
||||
void _VectorCopy (vec3_t in, vec3_t out);
|
||||
|
||||
int VectorCompare (vec3_t v1, vec3_t v2);
|
||||
vec_t VectorLength (vec3_t v);
|
||||
void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
|
||||
float VectorNormalize (vec3_t v); // returns vector length
|
||||
void VectorInverse (vec3_t v);
|
||||
void VectorScale (vec3_t in, vec_t scale, vec3_t out);
|
||||
int Q_log2(int val);
|
||||
|
||||
void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]);
|
||||
void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]);
|
||||
|
||||
void FloorDivMod (double numer, double denom, int *quotient,
|
||||
int *rem);
|
||||
fixed16_t Invert24To16(fixed16_t val);
|
||||
int GreatestCommonDivisor (int i1, int i2);
|
||||
|
||||
void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
|
||||
int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct mplane_s *plane);
|
||||
float anglemod(float a);
|
||||
|
||||
|
||||
#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \
|
||||
(((p)->type < 3)? \
|
||||
( \
|
||||
((p)->dist <= (emins)[(p)->type])? \
|
||||
1 \
|
||||
: \
|
||||
( \
|
||||
((p)->dist >= (emaxs)[(p)->type])?\
|
||||
2 \
|
||||
: \
|
||||
3 \
|
||||
) \
|
||||
) \
|
||||
: \
|
||||
BoxOnPlaneSide( (emins), (emaxs), (p)))
|
||||
|
||||
#endif /* __MATHLIB_H */
|
||||
|
||||
+2794
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright (C) 1996-2001 Id Software, Inc.
|
||||
Copyright (C) 2002-2009 John Fitzgibbons and others
|
||||
Copyright (C) 2010-2014 QuakeSpasm developers
|
||||
|
||||
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 _QUAKE_MENU_H
|
||||
#define _QUAKE_MENU_H
|
||||
|
||||
enum m_state_e {
|
||||
m_none,
|
||||
m_main,
|
||||
m_singleplayer,
|
||||
m_load,
|
||||
m_save,
|
||||
m_multiplayer,
|
||||
m_setup,
|
||||
m_net,
|
||||
m_options,
|
||||
m_video,
|
||||
m_keys,
|
||||
m_help,
|
||||
m_quit,
|
||||
m_lanconfig,
|
||||
m_gameoptions,
|
||||
m_search,
|
||||
m_slist
|
||||
};
|
||||
|
||||
extern enum m_state_e m_state;
|
||||
extern enum m_state_e m_return_state;
|
||||
|
||||
extern qboolean m_entersound;
|
||||
|
||||
//
|
||||
// menus
|
||||
//
|
||||
void M_Init (void);
|
||||
void M_Keydown (int key);
|
||||
void M_Charinput (int key);
|
||||
qboolean M_TextEntry (void);
|
||||
void M_ToggleMenu_f (void);
|
||||
|
||||
void M_Menu_Main_f (void);
|
||||
void M_Menu_Options_f (void);
|
||||
void M_Menu_Quit_f (void);
|
||||
|
||||
void M_Print (int cx, int cy, const char *str);
|
||||
void M_PrintWhite (int cx, int cy, const char *str);
|
||||
|
||||
void M_Draw (void);
|
||||
void M_DrawCharacter (int cx, int line, int num);
|
||||
|
||||
void M_DrawPic (int x, int y, qpic_t *pic);
|
||||
void M_DrawTransPic (int x, int y, qpic_t *pic);
|
||||
void M_DrawCheckbox (int x, int y, int on);
|
||||
|
||||
#endif /* _QUAKE_MENU_H */
|
||||
|
||||
+2282
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user