Merge branch 'next' into instant-setscale

This commit is contained in:
Logan Aerl Arias 2024-02-24 11:42:27 -05:00
commit 52f53f03b7
68 changed files with 3095 additions and 4522 deletions

View file

@ -94,7 +94,7 @@ default:
- - |
# apt_common
echo -e "\e[0Ksection_start:`date +%s`:apt_common[collapsed=true]\r\e[0KInstalling common packages"
- apt-get install make git ccache nasm
- apt-get install make git ccache nasm cmake ca-certificates
- |
# apt_common
echo -e "\e[0Ksection_end:`date +%s`:apt_common\r\e[0K"
@ -526,21 +526,22 @@ Windows x64:
Debian stable Clang:
stage: build
when: manual
when: on_success
allow_failure: true
allow_failure: false
artifacts:
paths:
- "bin/"
- "src/comptime.h"
- "build.clang/bin/"
- "build.clang/src/comptime.h"
expose_as: "clang"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-clang"
variables:
CC: clang
WFLAGS: -Wno-cast-align
CFLAGS: -Wno-cast-align
CXX: clang
WFLAGS: -Wno-cast-align -Wno-implicit-const-int-float-conversion -Werror
CFLAGS: -Wno-cast-align -Wno-implicit-const-int-float-conversion -Werror
LDFLAGS: -Wl,-fuse-ld=gold
script:
@ -560,10 +561,18 @@ Debian stable Clang:
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
- - |
# cmake
echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles"
- cmake -B build.clang -D CPM_USE_LOCAL_PACKAGES:BOOL=ON -D SRB2_CONFIG_ENABLE_TESTS:BOOL=OFF -D SRB2_CONFIG_SYSTEM_LIBRARIES:BOOL=ON -G "Unix Makefiles"
- |
# cmake
echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K"
- - |
# make
echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2"
- make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1
- make --directory=build.clang --keep-going || make --directory=src --keep-going
- |
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
@ -573,19 +582,22 @@ Debian testing Clang:
when: manual
allow_failure: true
image: debian:testing-slim
artifacts:
paths:
- "bin/"
- "src/comptime.h"
- "build.clang/bin/"
- "build.clang/src/comptime.h"
expose_as: "testing-clang"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-clang"
variables:
CC: clang
WFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype -Wno-single-bit-bitfield-constant-conversion
CFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype -Wno-single-bit-bitfield-constant-conversion
CXX: clang
WFLAGS: -Wno-cast-align -Wno-implicit-const-int-float-conversion -Werror -Wno-deprecated-non-prototype -Wno-single-bit-bitfield-constant-conversion
CFLAGS: -Wno-cast-align -Wno-implicit-const-int-float-conversion -Werror -Wno-deprecated-non-prototype -Wno-single-bit-bitfield-constant-conversion
LDFLAGS: -Wl,-fuse-ld=gold
Alpine 3 GCC:

View file

@ -1,93 +0,0 @@
================================================================
How to add Low-res modes to your XF86Config under Linux MANUALLY
================================================================
I TAKE NO RESPONSIBILITY FOR ANY DAMAGE DONE TO YOUR EQUIPMENT!!!
This document explains how to add low-res modes like 320x200 to your
X-Server configuration, because some new setup tools for the X-Server
do not support this. ONLY RECOMMENDED FOR USERS WHO KNOW WHAT THEY DO!
I do not take any responsibility for damage done to your monitor, your
videocard, your harddisk, your cat, your dog or anything else!!!
IMPORTANT IS, THAT YOUR "HorizSync" AND "VertRefresh" VALUES REALLY
MATCH YOUR MONITOR! OTHERWISE YOUR MONITOR CAN BLOW UP!!!
OK, if you have read up to here, you either know what you do or really
die-hard want those low-res modes. Here is what to do:
Look up your XF86Config. Is is either in /etc or in /etc/X11. Here is
what you have to add to the definition of your modeslines:
# Low-res Doublescan modes
# If your chipset does not support doublescan, you get a 'squashed'
# resolution like 320x400.
# 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio
Modeline "320x200" 12.588 320 336 384 400 200 204 205 225 Doublescan
# 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio
Modeline "320x240" 12.588 320 336 384 400 240 245 246 262 Doublescan
# 320x240 @ 72 Hz, 36.5 kHz hsync
Modeline "320x240" 15.750 320 336 384 400 240 244 246 262 Doublescan
# 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio
ModeLine "400x300" 18 400 416 448 512 300 301 302 312 Doublescan
# 400x300 @ 60 Hz, 37.8 kHz hsync
Modeline "400x300" 20 400 416 480 528 300 301 303 314 Doublescan
# 400x300 @ 72 Hz, 48.0 kHz hsync
Modeline "400x300" 25 400 424 488 520 300 319 322 333 Doublescan
If your video card only supports a specific set of discrete dotclocks
(RAMDAC) you may have to replace the dotclocks given here by one of the
specified (e.g in the first modeline the dotclock is 12.588 MHz). I believe
that nowadays all cards and monitors should work with these settings, but
if you have outdated hardware you better check the frequencies yourself. If
there is any uncertainty, please check the "XFree86 Video Timings HOWTO".
Then have a look at the section "Screen" with the appropriate driver
(usually either "svga" or "accel"). Under Subsection "Display" there
are modes for the given color depth. Add the desired modes. As an
example I give you my screens definition here with low-res modes in
16 bit color depth:
Section "Screen"
Driver "accel"
Device "3D Charger"
Monitor "Iiyama Pro 450"
DefaultColorDepth 16
Subsection "Display"
Depth 8
Modes "1280x1024" "1024x768" "800x600" "640x480"
ViewPort 0 0
Virtual 1280 1024
EndSubsection
Subsection "Display"
Depth 16
Modes "1152x864" "1024x768" "800x600" "640x480" "400x300" "320x200" <- THIS IS ACTUALLY WHAT YOU WANT!!!
ViewPort 0 0 ^^^^^^^^^^^^^^^^^^^
Virtual 1152 864
EndSubsection
Subsection "Display"
Depth 24
Modes "800x600" "640x480"
ViewPort 0 0
Virtual 800 600
EndSubsection
Subsection "Display"
Depth 32
Modes "800x600" "640x480"
ViewPort 0 0
Virtual 800 600
EndSubsection
EndSection
Once again: important is, that you edit the correct Screen section.
If you use the SVGA Server and edit the ACCEL Server, you might
wonder where your new modes have gone.
If everything went fine and you want to say thank you, just write
to "metzgermeister@users.sourceforge.net". If your monitor blew
up and you want to kill me, find me playing Legacy or Q3A on the net
and frag me (with your second monitor, hehe).
- metzgermeister

View file

@ -1,212 +0,0 @@
1-99 : Player Starts
1 - Player 1 Start 1
2 - Player 2 Start 2
3 - Player 3 Start 3
4 - Player 4 Start 4
5 - Player 5 Start 4001
6 - Player 6 Start 4002
7 - Player 7 Start 4003
8 - Player 8 Start 4004
9 - Player 9 Start 4005
10 - Player 10 Start 4006
11 - Player 11 Start 4007
12 - Player 12 Start 4008
13 - Player 13 Start 4009
14 - Player 14 Start 4010
15 - Player 15 Start 4011
16 - Player 16 Start 4012
17 - Player 17 Start 4013
18 - Player 18 Start 4014
19 - Player 19 Start 4015
20 - Player 20 Start 4016
21 - Player 21 Start 4017
22 - Player 22 Start 4018
23 - Player 23 Start 4019
24 - Player 24 Start 4020
25 - Player 25 Start 4021
26 - Player 26 Start 4022
27 - Player 27 Start 4023
28 - Player 28 Start 4024
29 - Player 29 Start 4025
30 - Player 30 Start 4026
31 - Player 31 Start 4027
32 - Player 32 Start 4028
33 - Player Match Start 11
34 - Red Team Start 87
35 - Blue Team Start 89
36 - Tag start New
100 - 199 : Enemies
100 - Blue Crawla 3004
101 - Red Crawla 9
102 - GFZ Fish 58
103 - Gold Buzz 5005
104 - Red Buzz 5006
105 - Jetty-Syn Bomber 3005
106 - Jetty-Syn Gunner 22
107 - Crawla Commander 21
108 - Deton 71
109 - Skim 56
110 - THZ Turret 2004
111 - Pop-up Turret 42
200 - 299 : Bosses and their associated items (if any)
200 - Boss 1 16
201 - Boss 2 2008
290 - Boss Fly Point 17
291 - EggTrap Center 2049
300 - 399 : Collectibles
300 - Ring 2014
301 - Homing Ring 69
302 - Rail Ring 3003
303 - Infinity Ring 80
304 - Automatic Ring 26
305 - Explosion Ring 54
306 - Red CTF Flag 31
307 - Blue CTF Flag 34
308 - Special Stage Token 2013
309 - Emerald 1 420
310 - Emerald 2 421
311 - Emerald 3 422
312 - Emerald 4 423
313 - Emerald 5 424
314 - Emerald 6 425
315 - Emerald 7 426
316 - Hunting Emerald 1 64
317 - Hunting Emerald 2 3002
318 - Hunting Emerald 3 3001
400 - 499 : Boxes
400 - Super Ring Box 2011
401 - Grey Ring Box 2012
402 - Ring Shield Box 48
403 - Fire Shield Box 2002
404 - Bomb Shield Box 2018
405 - Jump Shield Box 35
406 - Water Shield Box 2028
407 - Sneaker Box 25
408 - Invincibility Box 2022
409 - 1-Up Box 41
410 - Eggman Box 2005
411 - Mixup Box 78
412 - Question Box 3000
500 - 599 : Interactive Objects (friendly or otherwise - includes springs)
500 - Bubble Patch 33
501 - Level End Sign 86
502 - Starpost 3006
520 - Spike Ball -1
521 - Special Stage Spike Ball 23
522 - Ceiling Spike 67
523 - Floor Spike 68
540 - Fan 32
541 - Steam Riser 30
550 - Yellow Spring 28
551 - Red Spring 79
552 - Blue Spring 5004
553 - Yellow Spring Down 65
554 - Red Spring Down 66
555 - Yellow Diagonal Spring 2015
556 - Red Diagonal Spring 38
557 - Yellow Diag Spring Down 20
558 - Red Diag Spring Down 39
600 - 699 : Special placement patterns
600 - Vertical Rigns - Stack of 5 (suitable for Yellow Spring) 84
601 - Vertical Rings - Stack of 5 (suitable for Red Spring) 44
602 - Diagonal rings (5) 76
603 - Diagonal rings (10) 77
604 - A ring of rings 47
605 - A BIGGER ring of rings 2007
606 - A ring of wing items 2048
607 - A BIGGER ring of wing items 2010
608 - A ring of rings and wings (alternating) 2046
609 - A BIGGER ring of rings and wings (alternating) 2047
700 - 799 : Powerup indicators/environmental effects/miscellany
700 - Ambient Water 1a (S) 2026
701 - Ambient Water 1b (S) 2024
702 - Ambient Water 2a (M) 2023
703 - Ambient Water 2b (M) 2045
704 - Ambient Water 3a (L) 83
705 - Ambient Water 3b (L) 2019
706 - Ambient Water 4a (XL) 2025
707 - Ambient Water 4b (XL) 27
708 - Random Ambient 1 14
709 - Random Ambient 2 43
750 - Chaos Spawner 8
751 - Teleport Point 5003
752 - Alternate View Point 5007
753 - Zoom Tube Waypoint 18
754 - Pusher 5001
755 - Puller 5002
756 - Street Light 2003
800 - 899 : Greenflower Scenery
800 - Flower 1 36
801 - Flower 2 70
802 - Flower 3 73
804 - Berry Bush 74
805 - Bush 75
900 - 999 : Techno Hill Scenery
900 - THZ Plant 2035
901 - Alarm 2006
1000 - 1099 : Deep Sea Scenery
1000 - Gargoyle 81
1100 - 1199 : Castle Eggman Scenery
1100 - Ceiling Chain 49
1101 - Torch Flame 24
1102 - Eggman Statue 52
1103 - CEZ Flower 2001
1200 - 1299 : Arid Canyon Scenery
1300 - 1399 : Red Volcano Scenery
1400 - 1499 : Dark City Scenery
1500 - 1599 : Doom Ship Scenery
1600 - 1699 : Egg Rock/Final Fight Scenery
1700 - 1799 : NiGHTS Items
1700 - Axis 72
1701 - Axis Transfer (Normal) 61
1702 - Axis Transfer (Line) 46
1703 - Nights Drone 60
1704 - Nights Bumper 82
1705 - Hoop 57
1706 - Nights Wing 37
1707 - Super Loop Powerup 3007
1708 - Drill Refill Powerup 3008
1709 - Helper Powerup 3009
1710 - Egg Capsule 40
1800 - 1849 : Mario Items
1800 - Coin 10005
1801 - Goomba 10000
1802 - Blue Goomba 10001
1803 - FireFlower 50
1804 - Shell 10
1805 - Puma 29
1806 - Koopa 19
1807 - Axe 12
1808 - Mario Bush 1 10002
1809 - Mario Bush 2 10003
1810 - Toad 10004
1850 - 1899 : Christmas Items
1850 - Xmas Pole 5
1851 - Candy Cane 13
1852 - Snowman 6
1900 - 1999 : Misc Scenery
1900 - Stalagmite 0
1901 - Stalagmite 1
1902 - Stalagmite 2
1903 - Stalagmite 3
1904 - Stalagmite 4
1905 - Stalagmite 5
1906 - Stalagmite 6
1907 - Stalagmite 7
1908 - Stalagmite 8
1909 - Stalagmite 9

View file

@ -1,223 +0,0 @@
Description OldNum NewNum Description
Old Water 14 Removed
Level Parameters/Misc:
Per-Sector Gravity 64 1
Custom Exit 71 2
Zoom Tube Parameters 18 3
Speed Pad 65 4
Camera Scanner 63 5
Disable Linedef 73 6
Flat Alignment 66 7
Sector Special Parameters New 8
Mace Parameters New 9
Sprite Cull Height New 10
Rope Hang Parameters New 11
Rock Spawner Parameters New 12
PolyObjects
Marks first line in PolyObject New 20
Explicitly includes a PolyObject line New 21
PolyObject: Parameters New 22
PolyObject: Waving Flag New 31
Level-Load Effects:
Instant Floor Lower 26 50
Instant Ceiling Raise 24 51
Continuously Falling Sector 88 52
Continuous Floor/Ceiling Mover 2 53
Continuous Floor Mover 3 54
Continuous Ceiling Mover 4 55
Continuous Two-Speed Floor/Ceiling Mover 6 56
Continuous Two-Speed Floor Mover 7 57
Continuous Two-Speed Ceiling Mover 8 58
Activate Floating Platform 232 59
Activate Floating Platform (Adjustable Speed) 233 60
Crusher 1 (Ceiling to Floor) 43 61
Crusher 2 (Floor to Ceiling) 50 62
Fake Floor/Ceiling 242 63
Appearing/Disappearing FOF New 64
Bridge Thinker New 65
Floor Over Floors:
"Floor Over Floor: Solid, Opaque, Shadowcasting " 25 100
"Floor Over Floor: Solid, Opaque, Non-Shadowcasting " 33 101
"Floor Over Floor: Solid, Translucent " 44 102
"Floor Over Floor: Solid, Sides Only " 69 103
"Floor Over Floor: Solid, No Sides " 51 104
"Floor Over Floor: Solid, Invisible " 57 105
"Floor Over Floor: Water, Opaque " 48 120
"Floor Over Floor: Water, Translucent " 45 121
"Floor Over Floor: Water, Opaque, No Sides " 75 122
"Floor Over Floor: Water, Translucent, No Sides " 74 123
"Floor Over Floor: Platform, Opaque " 59 140
"Floor Over Floor: Platform, Translucent " 81 141
"Floor Over Floor: Platform, Translucent, No Sides " 77 142
Floor Over Floor: Bobbing (Air) 38 150
Floor Over Floor: Adjustable Bobbing (Air) 68 151
Floor Over Floor: Reverse Adjustable Bobbing (Air) 72 152
"Floor Over Floor: Floating, Bobbing " 34 160
Floor Over Floor: Crumbling (Respawn) 36 170
Floor Over Floor: Crumbling (No Respawn) 35 171
"Floor Over Floor: Crumbling (Respawn), Platform " 79 172
"Floor Over Floor: Crumbling (No Respawn), Platform " 80 173
"Floor Over Floor: Crumbling (Respawn), Platform, Translucent " 82 174
"Floor Over Floor: Crumbling (No Respawn), Platform, Translucent " 83 175
"Floor Over Floor: Crumbling (Respawn), Floating, Bobbing " 39 176
"Floor Over Floor: Crumbling (No Respawn), Floating, Bobbing " 1 177
"Floor Over Floor: Crumbling (Respawn), Floating " 37 178
"Floor Over Floor: Crumbling (No Respawn), Floating " 42 179
"Floor Over Floor: Crumbling (Respawn), Bobbing (Air) " 40 180
"Floor Over Floor: Rising Platform, Solid, Opaque, Shadowcasting " 89 190
"Floor Over Floor: Rising Platform, Solid, Opaque, Non-Shadowcasting " 90 191
"Floor Over Floor: Rising Platform, Solid, Translucent " 91 192
"Floor Over Floor: Rising Platform, Solid, Invisible " 94 193
"Floor Over Floor: Rising Platform, Platform, Opaque " 92 194
"Floor Over Floor: Rising Platform, Platform, Translucent " 93 195
Floor Over Floor: Light Block 49 200
Floor Over Floor: Half Light Block 47 201
Floor Over Floor: Fog Block 46 202
"Floor Over Floor: Intangible, Opaque " 62 220
"Floor Over Floor: Intangible, Translucent " 52 221
"Floor Over Floor: Intangible, Sides Only " 67 222
"Floor Over Floor: Intangible, Invisible " 58 223
Floor Over Floor: Mario Block 41 250
Floor Over Floor: Thwomp Block 54 251
Floor Over Floor: Shatter Block 76 252
"Floor Over Floor: Shatter Block, Translucent " 86 253
Floor Over Floor: Bustable Block 55 254
Floor Over Floor: Spin Bust Block 78 255
"Floor Over Floor: Spin Bust Block, Translucent " 84 256
Floor Over Floor: Quicksand Block 56 257
Floor Over Floor: Laser Block 53 258
Floor Over Floor: Custom 87 259
Linedef Executor Triggers:
Trigger Linedef Executor (Continuous) 96 300
Trigger Linedef Executor (Each Time) 97 301
Trigger Linedef Executor (Once) 98 302
Trigger Linedef Executor (Ring Count - Continuous) 95 303
Trigger Linedef Executor (Ring Count - Once) 99 304
Trigger Linedef Executor (Character Ability - Continuous) 19 305
Trigger Linedef Executor (Character Ability - Each Time) 20 306
Trigger Linedef Executor (Character Ability - Once) 21 307
"Trigger Linedef Executor (Race Only, Once) " 9 308
Trigger Linedef Executor (CTF Red Team - Continuous) 10 309
Trigger Linedef Executor (CTF Red Team - Each Time) 11 310
Trigger Linedef Executor (CTF Blue Team - Continuous) 12 311
Trigger Linedef Executor (CTF Blue Team - Each Time) 13 312
Trigger Linedef Executor (No More Enemies - Once) 15 313
Trigger Linedef Executor (# of Pushables - Continuous) New 314
Trigger Linedef Executor (# of Pushables - Once) New 315
Trigger Linedef Executors (PolyObject - Land On) New 316
Trigger Linedef Executor (Level Load) New 399
Linedef Executor Options:
Linedef Executor: Set Tagged Sector's Floor Height/Pic 101 400
Linedef Executor: Set Tagged Sector's Ceiling Height/Pic 102 401
Linedef Executor: Set Tagged Sector's Light Level 103 402
Linedef Executor: Move Tagged Sector's Floor 106 403
Linedef Executor: Move Tagged Sector's Ceiling 107 404
Linedef Executor: Lower Floor by Line 108 405
Linedef Executor: Raise Floor by Line 109 406
Linedef Executor: Lower Ceiling by Line 110 407
Linedef Executor: Raise Ceiling by Line 111 408
Linedef Executor: Change Calling Sector's Tag 112 409
Linedef Executor: Change Front Sector's Tag 114 410
Linedef Executor: Stop Plane Movement 116 411
Linedef Executor: Teleport Player to Tagged Sector 104 412
Linedef Executor: Change Music 105 413
Linedef Executor: Play SFX 115 414
Linedef Executor: Run Script 113 415
Linedef Executor: Start Adjustable Fire Flicker 119 416
Linedef Executor: Start Adjustable Glowing Light 120 417
Linedef Executor: Start Adjustable Strobe Flash (unsynchronized) New 418
Linedef Executor: Start Adjustable Strobe Flash (synchronized) New 419
Linedef Executor: Fade Light Level 117 420
Linedef Executor: Stop Lighting Effect 118 421
Linedef Executor: Cut-Away View 121 422
Linedef Executor: Change Sky 123 423
Linedef Executor: Change Weather 124 424
Linedef Executor: Change Object State 125 425
Linedef Executor: Stop Object 122 426
Linedef Executor: Award Score 126 427
Linedef Executor: Start Platform Movement 127 428
Linedef Executor: Crush Ceiling Once New 429
Linedef Executor: Crush Floor Once New 430
Linedef Executor: Crush Floor & Ceiling Once New 431
Linedef Executor: Enable 2D Mode New 432
Linedef Executor: Disable 2D Mode New 433
Linedef Executor: Award Custom Power New 434
Linedef Executor: Stop Conveyor New 435
Linedef Executor: Start Conveyor New 436
Linedef Executor: Disable Player Movement New 437
Linedef Executor: Execute Linedef Executor New 450
Linedef Executor: PolyObject: Door Slide New 480
Linedef Executor: PolyObject: Door Swing New 481
Linedef Executor: PolyObject: Move XY New 482
Linedef Executor: PolyObject: Move XY w/ override New 483
Linedef Executor: PolyObject: Rotate Right New 484
Linedef Executor: PolyObject: Rotate Right w/ override New 485
Linedef Executor: PolyObject: Rotate Left New 486
Linedef Executor: PolyObject: Rotate Left w/ override New 487
Linedef Executor: PolyObject: Start waypoint movement New 488
Linedef Executor: PolyObject: Make Invisible New 489
Linedef Executor: PolyObject: Make Visible New 490
Scrollers/Pushers:
Scroll Wall First Side Left 100 500
Scroll Wall First Side Opposite Direction 85 501
Scroll Wall According to Linedef 254 502
Acc Scroll Wall According to Linedef 218 503
Disp Scroll Wall According to Linedef 249 504
Scroll Texture by Offsets 255 505
Scroll Floor Texture 251 510
Acc Scroll Floor Texture 215 511
Disp Scroll Floor Texture 246 512
Scroll Ceiling Texture 250 513
Acc Scroll Ceiling Texture 214 514
Disp Scroll Ceiling Texture 245 515
Carry Objects on Floor (no scroll) 252 520
Acc Carry Objects on Floor 216 521
Disp Carry Objects on Floor 247 522
Carry Objects on Ceiling 203 523
Acc Carry Objects on Ceiling 205 524
Disp Carry Objects on Ceiling 201 525
Scroll Floor Texture and Carry Objects 253 530
Acc Scroll Floor Texture and Carry Objects 217 531
Disp Scroll Floor Texture and Carry Objects 248 532
Scroll Ceiling Texture and Carry Objects 202 533
Acc Scroll Ceiling Texture and Carry Objects 204 534
Disp Scroll Ceiling Texture and Carry Objects 200 535
Friction 223 540
Horizontal Wind 224 541
Upwards Wind 229 542
Downwards Wind 230 543
Horizontal Current 225 544
Upwards Current 227 545
Downwards Current 228 546
Boom Push/Pull Thing 226 547
Lighting:
Floor Lighting 213 600
Ceiling Lighting 5 601
Adjustable Pulsating Light 60 602
Adjustable Flickering Light 61 603
Adjustable Blinking Light (unsynchronized) New 604
Adjustable Blinking Light (synchronized) New 605
Colormap 16 606

Binary file not shown.

View file

@ -1,78 +0,0 @@
Removed:
- Buttons 1-20 690-709
- Button 21 (THZ2 A/740 B/741 D/742 E/745 710
- Close Door Blazing (Tag 743) 711
- Raise Ceiling to Highest (Tag 744) 981
- THZ2 Slime Raise (B/712 W713 P714 D715 S716) 986
Stuff to Remove/Change:
- Light Blinks On Every 0.5 Seconds 2 Add Linedef Combine
- Light Blinks On Every 1 Second 3 Add Linedef Combine
- Light Pulses Smoothly 8 Remove
- Light Blinks On Every 0.5 Seconds (Sync) 12 Add Linedef Combine
- Lights Blinks On Every 1 Second (Sync) 13 Add Linedef Combine
- Light Flickers Like Fire 17 Remove
? - Damage (Fire) and Current 519 Remove (convert to combination)
? - Damage (Water) and Current 984 Remove (convert to combination)
Section 1:
1 - Damage (Generic) 11
2 - Damage (Water) 983
3 - Damage (Fire) 7
4 - Damage (Electrical) 18
5 - Spikes 4
6 - Death Pit (Camera Mod) 16
7 - Death Pit (No Camera Mod) 5
8 - Instant Kill 10
9 - Ring Drainer (Floor Touch) 978
10 - Ring Drainer (No Floor Touch) 980
11 - Special Stage Damage 9
12 - Space Countdown 6
13 - Ramp Sector (Increase step-up) 992
14 - Non-Ramp Sector (Don't step-down) 996
15 - Bouncy Sector (FOF Control Only) 14
Section 2: << 4
1 - Trigger Linedef Exec (Pushable Objects) 971
2 - Trigger LD Exec (Anywhere in Sec/All Pls) 972
3 - Trigger Linedef Exec (Floor Touch/All Pls) 973
4 - Trigger Linedef Exec (Anywhere in Sec) 974
5 - Trigger Linedef Exec (Floor Touch) 975
6 - Trigger Linedef Exec (Emerald Check) 967
7 - Trigger Linedef Exec (NiGHTS Mare) 968
8 - Check for linedef executor on FOFs (ANY) 970
9 - Egg Trap Capsule 666
10 - Special Stage Time/Rings, Par 990
11 - Custom Global Gravity 991
Section 3: << 8
1 - Ice/Sludge (required?!) 256
2 - Wind/Current (required?!) 512
3 - Ice/Sludge and Wind/Current 768
4 - Conveyor Belt 985
5 - Speed Pad (No Spin) 976
6 - Speed Pad (Spin) 977
7 - Bustable Block Sprite Parameter 1500-1515
8 - "
9 - "
10 - "
11 - "
12 - "
13 - "
14 - "
15 - "
Section 4: << 12
1 - Starpost Activator 993
2 - Special Stage Goal Combine 33
2 - Exit Sector Combine 982
2 - No Tag Zone Combine 987
2 - CTF: Flag Return Combine 995
3 - CTF: Red Team Base 988
4 - CTF: Blue Team Base 989
5 - Fan Sector 997
6 - Super Sonic Transform 969
7 - Spinner 979
8 - Zoom Tube Start 998
9 - Zoom Tube End 999
10 - Finish Line 994

View file

@ -1,307 +0,0 @@
SRB2
Release v1.09, ? 2005.
Last Updated: June 2005
Original game & sources by: Id Software.
Additions: (c)1998 by: Fabrice Denis & Boris Pereira
(c)1999 by: Fabrice Denis, Boris Pereira & Thierry Van Elsuwe
(c)2000 by: Boris Pereira & Thierry Van Elsuwe
(c)2004 By: AJ, Graue, Alam Arias, Logan Arias & Andrew Clunis
Special thanks to Steven McGranahan, Lee Killough, Robert Bäuml and Bell Kin for
their large contribution and to other DooM LEGACY & SRB2 Team members.
Web site: http://www.SRB2.org/
e-mail: none@none.com
OpenGL specific:
Web site: http://legacy.newdoom.com/gl
-----------------------------------------------------------------------
F.A.Q.
-----------------------------------------------------------------------
If you have any trouble with SRB2, you might find a solution
here.
If you find a solution to a problem that was not listed here,
please tell us so that we can update the FAQ and help other people!
Mail your hardware/software problems to:
None@none.com subject: FAQ
--------
CONTENTS
--------
[0] Miscellaneous
[1] Mouse/Joystick/Keyboard
[2] Video
[3] Sound
[4] Network
[5] Troubleshooting
-----------------
[0] MISCELLANEOUS
-----------------
* under win95 or OS/2, I don't have enough memory. How can i handle with ?
Tell win95 to put more dpmi memory for your dos box.
Or use the -mb option.
---------------------------
[1] MOUSE/JOYSTICK/KEYBOARD
---------------------------
* My mouse/joystick does not work in SRB2.
First, check that the mouse/joystick is activated : go at the
console and type either 'use_mouse' (or use the respective
menuitem) or 'use_joystick'.
If it tells '0' or off than the mouse/joystick is not used,
set the variable to 1. eg: 'use_mouse 1'.
For the joystick, different values will support different
types of joystick, check the console documentation for the
command 'use_joystick' for more.
Even if the mouse or joystick is activated, you have to
set up the contols into the Setup Controls menu. That is:
tell what use you will make of the mouse/joystick buttons.
---------
[2] VIDEO
---------
* Where are the other video modes ? I have only '320x200' in the
Video Modes menu.
DOS
---
SRB2 adds new video modes only if a VESA2 (or better) driver
is present. The VESA2 driver is a standard of 'talking' between a
program and the huge amount of different graphics cards
available today.
If you don't have a VESA2 driver, you can download UNIVBE, or
SMART DISPLAY DOCTOR from
http://www.scitechsoft.com/products/ent/free_titles.html
or if you have an S3 based card, you can download the free
software called 'S3VBE'.
ftp://ftp.externet.hu/pub/mirror/sac/graph/s3vbe318.zip
ftp://ftp.digsys.bg/pub/simtelnet/msdos/graphics/s3vbe318.zip
http://www.filesearching.com/cgi-bin/s?q=s3vbe318.zip
http://www.google.com/search?q=s3vbe318.zip
* The game doesn't restore the video mode I have chosen the last time
I played SRB2.
The current video mode has to be made the 'default' so that it is
saved to the config : press the key 'D' on the Video Options menu
to set the current video mode the default.
* I have some problems with OpenGL mode
Have a look at the FAQ for OpenGL on the glLegacy web site:
http://www.doomnation.com/gllegacy/faqe.htm
# Linux: I only have a 1024x768 (or 800x600, 1280x1024, ...) resolution
in fullscreen mode under X and SRB2 is really really slow. Can I
have lower resolutions like 320x200 in fullscreen mode as well?
Probably yes. SRB2 can only use the resolutions offered by the
X-Server. So if all fullscreen modes have a very high resolution you
have to modify /etc/XF86Config (or /etc/X11/XF86Config). Use XF86Setup
(or the appropriate tool coming with your distribution - sax,
xf86config, ...) to do this.
If you do not succeed there, you can enter them manually into your
XF86Config file. ONLY RECOMMENDED FOR USERS WHO KNOW WHAT THEY DO!
For a short guide on how to do this, have a look at the file
"Doublescan.txt".
In case of doubt consult the XFree86-HOWTO (or ask your system
administrator :).
# Linux: I cannot have any fullscreen modes at all!
You have only modes above 1024x768 in your XF86Config. Proceed as
described above.
# Linux: After a certain idle time my screensaver jams the display of
SRB2. I can still operate SRB2, but I do not see what's happening
and the screensaver won't go away.
You probably have KDE. The KDE screensaver does not obey the screensaver
rules (at least mine, version 1.1). The solution is to deactivate the
KDE screensaver and use another screensaver (like the xscreensaver,
e.g.). But the hell, when you started SRB2 you should have played it
as well and not left it alone!!!
---------
[3] SOUND
---------
+ DOS:I can't have CD audio music, why ?
Make sure that the MSCDEX driver version 2.0 or later is loaded.
If it says 'MSCDEX version xxx' at game startup, and you still
don't hear the cd music, then probably your card doesn't respond
when SRB2 tries to set the cd volume. If so, make sure your sound
card's mixer have the cd volume set up so that you can hear something.
+ When the CD plays, the game is very 'jerky'. It doesn't do that when
I type 'cd off' in the console.
You have an old/bad cd driver, that can take up to a second to
respond to cd driver commands. Either get the latest version of
your driver, or turn cd update off. Check 'cd_udpate' in the
console documentation for more.
* DOS:How can I *ALWAYS* disable the sounds or music of the game ?
Edit the allegro.cfg file and set digicard/midicard to 0 (none)
* DOS:My sterero sound is reversed, how can I set it the right way ?
Change the console variable 'stereoreverse' to either 1 or 0.
Or, you can edit the allegro.cfg file, and set the 'flip_pan' variable.
* DOS:The sounds are too 'slow', or 'low-pitched'
It seems to be a problem of the auto-detection of some 8bit sound
cards. You will have to set manually the 'sb_freq' value in the
allegro.cfg file to a lower value : 11906, 16129.
* DOS:SRB2 doesn't play any sound/music, but I have a sound
blaster genuine/compatible card.
If you have a genuine or compatible SoundBlaster card, it is very
important that you set the BLASTER environment variable.
If you are playing under DOS, and never installed your sound card
under DOS, run the setup of your sound card for DOS.
Check if the BLASTER variable was set: type 'SET' under dos
(or DOSbox)
Do you see something like 'BLASTER=A220 I5 D1 ...' ?
Yes? If you don't hear sounds/music, then tweak the settings in the
allegro.cfg file until you get something, first try changing the
type of the sound card, it is not always properly detected.
No? You have to set this variable in order that your sound card is
detected. Run the setup that was shipped with your sound card, and
make sure you run the setup for DOS too, it will usually add a
line of the type 'SET BLASTER=... ...' in the autoexec.bat file.
* DOS:How can I have better midi music on my 8bit sound card ?
Use the DIGMID driver, it is supported in SRB2.
What the hell is this? Well, the Gravis Ultrasound uses digital
samples to play midi music. On a simple 8bit card, you can use digital
samples too, which will sound usually better than what is output
by the poor fm synthesis chip of 8bit cards.
You will need to get a Gravis Ultrasound patch set, you can find
several ones for free on internet, it consists of a bunch of '.pat'
files which are the digital samples to play the midi instruments
(eg: piano, conga, guitar, ect.).
Check the Allegro homepage for some links to GUS patches:
http://alleg.sourceforge.net/digmid.html
http://alleg.sourceforge.net/
http://www.talula.demon.co.uk/allegro/digmid.html
http://www.talula.demon.co.uk/allegro/
Now to activate the DIGMID driver:
Set the 'midi_card' value to 8 (DIGMID) in the allegro.cfg file.
Make sure you leave the 'digi_voices' blank, or set it to a low
value, because the midi music will use digital voices.
At the end of the allegro.cfg file, set the 'patches' value
to the path, where you have installed a Gravis Ultrasound midi
patch set. eg: patches = d:\music\midipat\
# Linux: CD music does not work or only works when run as root.
We do not encourage you to run SRB2 as root (you never know
what SRB2 can do to your system - it's a mighty piece of code :).
There is a common problem with ATAPI CD-rom drives, which are
treated as harddisks. Usually there is a link /dev/cdrom pointing to
device hd[b,c,d]. As harddisks are not supposed to be read directly
via this device (especially not by a common user), there are no read
permissions for "all". For CD-roms you can savely set read permissions
unless you are very paranoid. Assuming your CD-rom drive is /dev/hdc,
set permissions with "chmod +r /dev/hdc" (as root). SCSI CD-rom drives
should not have this problem. But if they do, proceed as described
with ATAPI drives.
# Linux: The CD music volume is not set properly.
Go to the console and type "jigglecdvolume 1".
-----------
[4] NETWORK
-----------
* Where can I find Internet servers ?
For the moment there is one public server.
http://srb2.servegame.org/ Master server web page
srb2.servegame.org:28910 current Master Server
* When I start SRB2 with -server or -connect it say :
"BinToPort: Address already in use (EADDRINUSE)"
It appears only when SRB2 crashes or when you leave with ctrl-break.
use -udpport 12345 (or any other free slot) on both sides (client and
server).
This can also happens when there is already a SRB2 running on your
computer if you whant to try two SRB2 running on the same computer
use -clientport 12345 (or any other free slot). Then the second will
connect to the first one.
* Do you use the tcp protocol ?
No, we use the udp protocol which is faster, but don't worry udp is a
part of the internet protocol.
-------------------
[5] Troubleshooting
-------------------
# Linux: SRB2 is hung in fullscreen mode and won´t let me leave.
What shall I do?
Some people press the reset button, but hey, we are not in the
stoneage of operating systems! There are two "proper" ways to
get out: kill your X-Server. You can usually do this by pressing
"CTRL-ALT-BACKSPACE". But if you have other open applications with
important data (probably hacked away on your diploma thesis for 3
weeks without saving once) you can also kill SRB2 directly. Press
"CTRL-ALT-F2" and you will get to a console. Log in, type
"killall llxSRB2" and switch back to the X-Server with "CTRL-ALT-F7".
Some X-Server crash on this procedure - blame the X-Server for the
loss of 3 weeks work on your diploma thesis :)

View file

@ -1,68 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>
Sonic Robo Blast 2 Manual
</title>
<link rel="stylesheet" type="text/css" href="srb2manstyle.css">
<!-- Borrowed some javascript code so the height of the iframe is equal to the size of the document - Sonict -->
<script type="text/javascript">
/* free code from dyn-web.com */
function getDocHeight(doc) {
doc = doc || document;
// from http://stackoverflow.com/questions/1145850/get-height-of-entire-document-with-javascript
var body = doc.body, html = doc.documentElement;
var height = Math.max( body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight );
return height;
}
function setIframeHeight(id) {
var ifrm = document.getElementById(id);
var doc = ifrm.contentDocument? ifrm.contentDocument: ifrm.contentWindow.document;
ifrm.style.visibility = 'hidden';
ifrm.style.height = "10px"; // reset to minimal height in case going from longer to shorter doc
ifrm.style.height = getDocHeight( doc ) + "px";
ifrm.style.visibility = 'visible';
}
</script>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8">
</head>
<body>
<p class="c1">
<img src="manual_img/sonicname2.png" alt="SONIC" width="136" height="36">
<br>
<img src="manual_img/srb2banner.png" alt="ROBO BLAST 2" width="224" height="43">
</p>
<p class="c1">
<big><big><strong>Manual</strong></big></big>
</p>
<table class="cf" align="center">
<tr><td class="c">
<ul class="hmenu">
<li class="hmenu"><a class="hmenu" href="intro.htm" target="ifrm">Main</a></li>
<li class="hmenu"><a class="hmenu" href="items.htm" target="ifrm">Items</a></li>
<li class="hmenu"><a class="hmenu" href="playerabilities.htm" target="ifrm">Player Abilities</a></li>
<li class="hmenu"><a class="hmenu" href="basicplay.htm" target="ifrm">Gameplay</a></li>
<li class="hmenu"><a class="hmenu" href="surroundings.htm" target="ifrm">Surroundings</a></li>
</ul>
</td></tr>
<tr><td class="c">
<ul class="hmenu">
<li class="hmenu"><a class="hmenu" href="multiplayer.htm" target="ifrm">Multiplayer</a></li>
<li class="hmenu"><a class="hmenu" href="zones.htm" target="ifrm">Zones</a></li>
<li class="hmenu"><a class="hmenu" href="controls.htm" target="ifrm">Controls</a></li>
<li class="hmenu"><a class="hmenu" href="consolecommands.htm" target="ifrm">Console Commands</a></li>
<li class="hmenu"><a class="hmenu" href="misc.htm" target="ifrm">Misc</a></li>
</ul>
</td></tr>
</table>
<hr>
<p class="c1">
<!-- The "onload" property of the iframe makes an error when validated through the W3C validation checker. -->
<!-- This will not be fixed as it isn't worth the time to fix it up properly. - Sonict -->
<iframe id="ifrm" name="ifrm" src="intro.htm" onload="setIframeHeight(this.id)"> </iframe>
</p>
</body>
</html>

View file

@ -1,39 +0,0 @@
SVN-RULES
- As you can see, there is sub-directory in the repository, one for eatch
platform (djgpp (dos),win32,SDL) the root directory is for all platform,
so take care of the order we have put in.
- do not commit/upload tests of bugged code, try to fix a maximum of know
bugs and update know bugs list in source.txt. If you must commit your source
make your code in #ifdef so we can disable it
- SRB2 is a modification of doom/Doom Legacy source. We allow additionnal feature
and visual addition.
- Maximize communications between members, do not impose your changes, if your
are not sure about a feature/change, talk about it in irc://irc.esper.net/srb2 chat room.
CODE-RULES
- We use no tab, 4 space indent, and tab size 8 (in case some tab have filtred
and for makefile)
- Self documented code, variable and function must have a name that help
understand the code, so do not call variable and function a,b, a2, ...
- the usage of extern in a c file is prohibited, except for declaration of a
function with body (so it is like public keyword in c++)
Also function protos haren't allowed for external function, put it un the
corresponding h file.
- Try to minimize #ifdef usage for :
- code readability
- the main code is for all port so if something is good for a platform all
platform can benefit by this feature
- Take care of platform dependent code, we would like to have code that work
on Dos, Win32, SDL, ... little and big endian, software/Glide/OpenGl.
GOOD PRACTICE
- Try to put as mush static variable and function on module so it help to
understand the role of the varaible/function in the module also this
help the compiler to optimize
- minimise global variable
- make a log of your work, so you don't need to put a lot of comment in
the code, this will also help us to update the what's new section of doc
when doing final release

View file

@ -1,240 +0,0 @@
1. Compile SRB2
2. Explanation of the code
2.1 The memory model
2.2 Hardware Texture model
1. Compile SRB2
=================
DOS
---
need:
- djgpp 2.03 (http://www.delorie.com/djgpp/)
- allegro 3.12 (http://alleg.sourceforge.net/index.html)
(
- libsocket 0.7.4 (beta 4) or better
for use with Winsock 1.1 (example Windows 3.1)
(http://www.phekda.freeserve.co.uk/richdawe/lsck/lsck.htm)
OR
- Wattcp-32 v2.2 dev.rel 6 or better
For use with a packet driver
(http://www.bgnett.no/~giva/)
(http://groups.yahoo.com/group/watt-32/)
(http://groups.yahoo.com/group/watt-32/files/v2.2/)
)
- bcd 1.03 (inlcude in this package)
- gcc 2.95.2 is recommended
- nasm 0.98 (or better) (http://nasm.sourceforge.net/)
compile:
make
make WATTCP=1 (to make a Wattcp-32 version)
debug:
when craching SRB2 will return eip
type make asm, then you will have a 8 megs srb2.s (a assembler file)
the you can find the faulting instruction and function
------------------------------------------------------------------------
Linux/SDL
-----
need:
- tested with gcc 2.95 and 3.X.
- SDL 1.2
- SDL_mixer 1.2
- ibogg and libvorbis (http://Xiph.org/)
- nasm 0.98 (or better)(http://nasm.sourceforge.net/) only with 2.95, else add CC30=1
compile
make LINUX=1
debug:
gdb ?
------------------------------------------------------------------------
Win32
-----
need :
- glide 3.x sdk (optional) (http://www.3dfx.com)
- directx6 sdk (or higher) (http://www.micosoft.com/directx)
- nasm 0.98 (or better) (http://nasm.sourceforge.net/)
- use src\win32\wLegacy.dsp
- VC6 should also work with VC5, and VS.NET 200X
debug:
press on "step over" with the release version (there is some debug info
on it). Then change the eip in the regster window when you will type
enter the edi will go to the faulting instruction. don't forget that
you can follow the stack for calls.
You can also use trace with the debug version but add -win and -nomouse.
------------------------------------------------------------------------
Win32/minGW/SDL
-----
need:
- tested with gcc 2.95 and 3.X.
- can also use Dev-C++ 5.0 beta 9 (4.9.9.0) from http://www.bloodshed.net/dev/devcpp.html
- SDL 1.2
- SDL_mixer 1.2
compile
make minGW=1 SDL=1
or use src\SDL\Win32SDL.dev with Dev-C++ 4.9.9.0 or later
debug:
gdb ?
------------------------------------------------------------------------
WinCE/SDL WIP
-----
need:
- ActiveSync 3.8
http://www.microsoft.com/windowsmobile/downloads/activesync38.mspx
- ActiveSync 3.7.1, if 3.8 isn't available for your language
http://www.microsoft.com/windowsmobile/downloads/activesync37.mspx
- eMbedded Visual Tools 3.0 - 2002 Edition
http://www.microsoft.com/downloads/details.aspx?FamilyID=f663bf48-31ee-4cbe-aac5-0affd5fb27dd
- Pocket PC 2000 SDK
http://www.microsoft.com/downloads/details.aspx?FamilyID=bb3f4d7b-de2a-4e1a-a175-26a68c301ac4
- Pocket PC 2002 SDK (eMVT 3.0 2002 Ed. comes with this)
http://www.microsoft.com/downloads/details.aspx?FamilyID=2dbee84a-bd94-4167-b817-2b2e548b2e92
- Pocket PC 2002 SDK Emulator Images (eMVT 3.0 2002 Ed. comes with this)
http://www.microsoft.com/downloads/details.aspx?FamilyID=25f4de97-ae80-477a-9df1-496b85b3d3e3
- eMbedded Visual C++ 4.0
http://www.microsoft.com/downloads/details.aspx?familyid=1DACDB3D-50D1-41B2-A107-FA75AE960856
- eMbedded Visual C++ 4.0 SP3 (Win CE 4.0-4.2)
http://www.microsoft.com/downloads/details.aspx?FamilyID=5bb36f3e-5b3d-419a-9610-2fe53815ae3b
OR
- eMbedded Visual C++ 4.0 SP4 (No SH3 support,Win CE 4.0-5.0 support)
http://www.microsoft.com/downloads/details.aspx?FamilyID=4a4ed1f4-91d3-4dbe-986e-a812984318e5
- eMbedded Visual C++ 4.0 Update 5625 (SP4 only)
http://www.microsoft.com/downloads/details.aspx?FamilyID=aa282a6d-6f57-436d-8c10-0ec02d94f5b1
- Windows CE: Standard Software Development Kit
http://www.microsoft.com/downloads/details.aspx?familyid=a08f6991-16b0-4019-a174-0c40e6d25fe7
- SDK for Windows Mobile 2003-based Pocket PCs
http://www.microsoft.com/downloads/details.aspx?FamilyId=9996B314-0364-4623-9EDE-0B5FBB133652
- Emulator Images for Windows Mobile 2003 Second Edition software for Pocket PC
http://www.microsoft.com/downloads/details.aspx?familyid=5C53E3B5-F2A2-47D7-A41D-825FD68EBB6C
- Microsoft Device Emulator 1.0 Community Preview
http://beta.microsoft.com Use Guest ID "MSDEVICE" to access the Community Preview website
- Windows CE Utilities for Visual Studio .NET 2003 Add-on Pack 1.1
(if you also have VS 2003 installed, you need this to install Win CE 5.0 SDK, else no need)
http://www.microsoft.com/downloads/details.aspx?FamilyId=7EC99CA6-2095-4086-B0CC-7C6C39B28762
- Windows CE 5.0: Standard Software Development Kit (eMC++ 4 SP4 only)
http://www.microsoft.com/downloads/details.aspx?FamilyID=fa1a3d66-3f61-4ddc-9510-ae450e2318c3
- SDL 1.27 (use patch and zip in tools\SDL1.2.7_CE)
compile
use src\SDL\WinCE\SRB2CE.vcw
debug:
?
2. Explanation of the code
==========================
2.1 The memory model (original) (z_zone.c) (by BP)
--------------------
SRB2 allocate a heap of 6/32/48 megs at begining and provide a Z_Malloc function
to allocate in this heap.
Z_Malloc( int size,int tag,void* user )
size is the size in byte
tag can be : PU_STATIC allocated static (like malloc do)
call Z_Free to free it
PU_LEVEL same as static but the zone is "tagged" with the
tag PU_LEVEL, when calling
Z_FreeTag (PU_LEVEL, PU_LEVEL) all zone tagged
with PU_LEVEL are freed (at the end of the level)
PU_CACHE this one _can_ be freed automatiquely by one other
call to Z_Malloc. the *user point to a pointer
to this zone so when freed automatiquely the
pointer is set to NULL so eatch time you use it
you must check if the pointer is not NULL and
reload it.
(...)
2.2 Hardware Texture model (by BP)
--------------------------
Eatch texture/patch/flats/pic in SRB2 are converted to hardware texture at
runtime (the GlideMipmap_s structure (hw_data.h)). I will call hardware
texture a gr_texture so there is no confusion.
To remind you :
- Texture are set of patch and are associate to linedefs (walls) can be
upper, lower or middle texture. It can have hole on it.
- patch are sprites (the doom patch are run of vertical lines)
- flats are used for floors and ceiling of sectors and have size of 64x64
it can't have hole on it
- pic are new legacy format for picture, it can only handle plain texture
like flats it is now used for hud in full screen for the main picture
of legacy and for coronas (the format was extended to handle 32 bit color
or intensity + alpha, not all are implemented at this time)
Since patch, flat and pic are basic structure represented by only one lump in
the wad, the wad loader allocate for eatch lump a GlideMipmap_s (cache3Dfx)
and init data field to NULL. Since the data structure is allocated in
PU_3DFXCACHE (like PU_CACHE) the data will be initilised when needed
(hw_cache.c).
The GlideMipmap_s structures for textures are initialized on
HWR_PrepLevelCache (hw_cache.c) it is called in P_SetupLevel (load level)
the number of textures is computed with TEXTURE1, TEXTURE2 lumps since this
can be changed in runtime in SRB2 (load a wad while runing) it must be
reallocated. Well, at this time it is realloceted at eatch level start. We
can do better, since numtextures change only when a wad is loaded.
The 3dfx driver use glide3, it load gr_texture in gr_texture memory of the
card in fifo order when there is no more place it remove the first gr_texture,
the downloaded field of GlideMipmap_s go to false and when needed it is
reloaded in gr_texture memory. In OpenGl, since OpenGl keep texture in there
own memory and handle gr_texture memory of the card we no more need to
redownload it but if we not free time to time gr_texture memory in opengl,
it will get alot of memory, so the gr_texture memory is cleared at eatch
new level (same time of texture reallocation). Opengl and 3dfx link the
loaded gr_texture with the nextmipmap field of GlideMipmap_s so before clear
textures of the heap we MUST free gr_texture memory of OpenGl or 3dfx !
SRB2 can also draw patch with a differant colormap (thanks to Hurdler).
When needed it create the same gr_texture but just with a differant colormap.
This one is linked with the original in the GlideMipmap_s with the
nextcolormap field.
So when a polygone with a gr_texture must be drawn, first we check if the
gr_textures is not allready loaded in hadware memory (downloaded field) if
not then we check if gr_texture data is there (not grabbed by z_malloc
function) if not we must recompute it eatch type of gr_texture (texture,
patch, flat, pic have there own methode) the we can send the gr_texture
to 3dfx or OpenGl.

File diff suppressed because it is too large Load diff

311
doc/specs/udmf_srb2.txt Normal file
View file

@ -0,0 +1,311 @@
===============================================================================
Universal Doom Map Format Sonic Robo Blast 2 extensions v1.0 19.02.2024
Copyright (c) 2024 Sonic Team Junior
uses Universal Doom Map Format Specification v1.1 as a template,
original document Copyright (c) 2009 James Haley.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
===============================================================================
This document discusses the UDMF implementation found in Sonic Robo Blast 2's engine.
=======================================
I. Grammar / Syntax
=======================================
No changes.
=======================================
II. Implementation Semantics
=======================================
------------------------------------
II.A : Storage and Retrieval of Data
------------------------------------
No changes.
-----------------------------------
II.B : Storage Within Archive Files
-----------------------------------
No changes.
--------------------------------
II.C : Implementation Dependence
--------------------------------
The SRB2 engine only supports the following namespace:
"srb2"
The engine is allowed to refuse maps with an unsupported namespace,
or emit a warning.
=======================================
III. Standardized Fields
=======================================
The SRB2 engine ignores any user-defined fields.
All boolean fields default to false unless mentioned otherwise.
Sonic Robo Blast 2 defines the following standardized fields:
vertex
{
x = <float>; // X coordinate. No valid default.
y = <float>; // Y coordinate. No valid default.
zfloor = <float>; // Floor height at this vertex. Only applies to triangular sectors
zceiling = <float>; // Ceiling height at this vertex. Only applies to triangular sectors
}
linedef
{
id = <integer>; // ID of line. Interpreted as tag.
moreids = <string>; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
v1 = <integer>; // Index of first vertex. No valid default.
v2 = <integer>; // Index of second vertex. No valid default.
blocking = <bool>; // Line blocks things.
blockmonsters = <bool>; // Line blocks enemies.
twosided = <bool>; // Line is 2S.
dontpegtop = <bool>; // Upper texture unpegged.
dontpegbottom = <bool>; // Lower texture unpegged.
skewtd = <bool>; // Upper and lower textures are skewed.
noclimb = <bool>; // Line is not climbable.
noskew = <bool>; // Middle texture is not skewed.
midpeg = <bool>; // Middle texture is pegged.
midsolid = <bool>; // Middle texture is solid.
wrapmidtex = <bool>; // Line's mid textures are wrapped.
nonet = <bool>; // Special only takes effect in singleplayer games.
netonly = <bool>; // Special only takes effect in multiplayer games.
bouncy = <bool>; // Line is bouncy.
transfer = <bool>; // In 3D floor sides, uses the sidedef properties of the control sector.
alpha = <float>; // Translucency of this line. Default is 1.0
renderstyle = <string>; // Render style. Can be:
// - "translucent"
// - "add"
// - "subtract"
// - "reversesubtract"
// - "modulate"
// - "fog"
// Default is "translucent".
special = <integer>; // Linedef action. Default = 0.
arg0 = <integer>; // Argument 0. Default = 0.
arg1 = <integer>; // Argument 1. Default = 0.
arg2 = <integer>; // Argument 2. Default = 0.
arg3 = <integer>; // Argument 3. Default = 0.
arg4 = <integer>; // Argument 4. Default = 0.
arg5 = <integer>; // Argument 5. Default = 0.
arg6 = <integer>; // Argument 6. Default = 0.
arg7 = <integer>; // Argument 7. Default = 0.
arg8 = <integer>; // Argument 8. Default = 0.
arg9 = <integer>; // Argument 9. Default = 0.
stringarg0 = <string>; // String argument 0.
stringarg1 = <string>; // String argument 1.
sidefront = <integer>; // Sidedef 1 index. No valid default.
sideback = <integer>; // Sidedef 2 index. Default = -1.
comment = <string>; // A comment. Implementors should attach no special
// semantic meaning to this field.
}
sidedef
{
offsetx = <integer>; // X offset. Default = 0.
offsety = <integer>; // Y offset. Default = 0.
texturetop = <string>; // Upper texture. Default = "-".
texturebottom = <string>; // Lower texture. Default = "-".
texturemiddle = <string>; // Middle texture. Default = "-".
repeatcnt = <string>; // Number of middle texture repetitions. Default = 0
sector = <integer>; // Sector index. No valid default.
scalex_top = <float>; // X scale for upper texture. Default = 1.0.
scaley_top = <float>; // Y scale for upper texture. Default = 1.0.
scalex_mid = <float>; // X scale for mid texture. Default = 1.0.
scaley_mid = <float>; // Y scale for mid texture. Default = 1.0.
scalex_bottom = <float>; // X scale for lower texture. Default = 1.0.
scaley_bottom = <float>; // Y scale for lower texture. Default = 1.0.
offsetx_top = <float>; // X offset for upper texture. Default = 0.0.
offsety_top = <float>; // Y offset for upper texture. Default = 0.0.
offsetx_mid = <float>; // X offset for mid texture. Default = 0.0.
offsety_mid = <float>; // Y offset for mid texture. Default = 0.0.
offsetx_bottom = <float>; // X offset for lower texture. Default = 0.0.
offsety_bottom = <float>; // Y offset for lower texture. Default = 0.0.
comment = <string>; // A comment. Implementors should attach no special
// semantic meaning to this field.
}
sector
{
heightfloor = <integer>; // Floor height. Default = 0.
heightceiling = <integer>; // Ceiling height. Default = 0.
texturefloor = <string>; // Floor flat. No valid default.
textureceiling = <string>; // Ceiling flat. No valid default.
lightlevel = <integer>; // Light level. Default = 255.
lightfloor = <integer>; // The floor's light level. Default is 0.
lightceiling = <integer>; // The ceiling's light level. Default is 0.
lightfloorabsolute = <bool>; // true = 'lightfloor' is an absolute value. Default is
// relative to the owning sector's light level.
lightceilingabsolute = <bool>; // true = 'lightceiling' is an absolute value. Default is
// relative to the owning sector's light level.
special = <integer>; // Sector special. Default = 0.
id = <integer>; // Sector tag/id. Default = 0.
moreids = <string>; // Additional sector IDs/tags, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
xpanningfloor = <float>; // X texture offset of floor texture. Default = 0.0.
ypanningfloor = <float>; // Y texture offset of floor texture. Default = 0.0.
xpanningceiling = <float>; // X texture offset of ceiling texture. Default = 0.0.
ypanningceiling = <float>; // Y texture offset of ceiling texture. Default = 0.0.
xscalefloor = <float>; // X texture scale of floor texture. Default = 1.0.
yscalefloor = <float>; // Y texture scale of floor texture. Default = 1.0.
xscaleceiling = <float>; // X texture scale of ceiling texture. Default = 1.0.
yscaleceiling = <float>; // Y texture scale of ceiling texture. Default = 1.0.
rotationfloor = <float>; // Rotation of floor texture in degrees. Default = 0.0.
rotationceiling = <float>; // Rotation of ceiling texture in degrees. Default = 0.0.
ceilingplane_a = <float>; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'.
ceilingplane_b = <float>; // 'heightceiling' will still be used to calculate texture alignment.
ceilingplane_c = <float>; // The plane equation will only be used if all 4 values are given.
ceilingplane_d = <float>; // The plane is defined as a*x + b*y + c*z + d = 0 with the normal vector pointing downward.
floorplane_a = <float>; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'.
floorplane_b = <float>; // 'heightfloor' will still be used to calculate texture alignment.
floorplane_c = <float>; // The plane equation will only be used if all 4 values are given.
floorplane_d = <float>; // The plane is defined as a*x + b*y + c*z + d = 0 with the normal vector pointing upward.
lightcolor = <integer>; // Sector's light color as RRGGBB value. Default = 0x000000.
lightalpha = <integer>; // Sector's light opacity. Default = 25.
fadecolor = <integer>; // Sector's fog color as RRGGBB value. Default = 0x000000.
fadealpha = <integer>; // Sector's fog opacity. Default = 25.
fadestart = <integer>; // Sector's fading range start. Default = 0.
fadeend = <integer>; // Sector's fading range end. Default = 31.
colormapfog = <bool>; // Sector's colormap uses fog lighting.
colormapfadesprites = <bool>; // Sector's colormap affects full-bright sprites.
colormapprotected = <bool>; // Sector's colormap is not affected by colormap change specials.
flipspecial_nofloor = <bool>; // Trigger effects that require a plane touch are not executed when the floor is touched.
flipspecial_ceiling = <bool>; // Trigger effects that require a plane touch are executed when the ceiling is touched.
triggerspecial_touch = <bool>; // Trigger effects are executed anywhere in the sector.
triggerspecial_headbump = <bool>; // Trigger effects are executed if the top of the triggerer object touches a plane.
triggerline_plane = <bool>; // Trigger effects require a plane touch to be executed.
triggerline_mobj = <bool>; // Trigger effects can be executed by non-pushable objects.
invertprecip = <bool>; // Inverts the precipitation effect; if the sector is considered to be indoors,
// precipitation is generated, and if the sector is considered to be outdoors,
// precipitation is not generated.
gravityflip = <bool>; // Sector flips any objects in it, if the sector has negative gravity.
heatwave = <bool>; // Sector has the heat wave effect.
noclipcamera = <bool>; // Sector is not tangible to the camera.
outerspace = <bool>; // Sector has the space countdown effect.
doublestepup = <bool>; // Sector has half the vertical height needed for objects to walk into it.
nostepdown = <bool>; // Sector has the staircase effect disabled.
speedpad = <bool>; // Sector is a speed pad.
starpostactivator = <bool>; // Sector activates any Star Posts in it when walked into by a plyer.
exit = <bool>; // Sector is an exit sector.
specialstagepit = <bool>; // Sector is a Special Stage pit.
returnflag = <bool>; // Sector returns any Capture the Flag flags that come in contact with it to their respective bases.
redteambase = <bool>; // Sector is a Red Team base.
blueteambase = <bool>; // Sector is Blue Team base.
fan = <bool>; // Sector is a fan sector.
supertransform = <bool>; // Sector transforms any players that come in contact with it into their 'super' mode.
forcespin = <bool>; // Sector forces any players that come in contact with it to roll.
zoomtubestart = <bool>; // Sector is the starting point of a zoom tube path.
zoomtubeend = <bool>; // Sector is the ending point of a zoom tube path.
finishline = <bool>; // Sector is a Circuit finish line.
ropehang = <bool>; // Sector is a rope hang. Must be applied to a 3D floor.
jumpflip = <bool>; // Sector flips the gravity of players who jump from it.
gravityoverride = <bool>; // Reverse gravity effect is only applied when an object is in the sector.
friction = <float>; // Sector's friction factor.
gravity = <float>; // Sector's gravity. Default is 1.0.
damagetype = <integer>; // Damage type for sector damage. Can be:
// - "None"
// - "Generic"
// - "Water"
// - "Fire"
// - "Lava"
// - "Electric"
// - "Spike"
// - "DeathPitTilt"
// - "DeathPitNoTilt"
// - "Instakill"
// - "SpecialStage"
// Default = "None".
triggertag = <integer>; // Tag to trigger when this sector is entered. Default = 0.
triggerer = <string>; // Who can execute the trigger tag when this sector is entered. Can be:
// - "Player"
// - "AllPlayers"
// - "Mobj"
// Default = "Player".
comment = <string>; // A comment. Implementors should attach no special
// semantic meaning to this field.
}
thing
{
id = <integer>; // Thing ID. Default = 0.
moreids = <string>; // Additional thing IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
x = <float>; // X coordinate. No valid default.
y = <float>; // Y coordinate. No valid default.
height = <float>; // Z height relative to floor.
// Relative to ceiling if flip = true.
// Absolute if absolutez = true.
// Default = 0.
angle = <integer>; // Map angle of thing in degrees. Default = 0 (East).
pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
roll = <integer>; // Roll of thing in degrees. Default = 0.
scalex = <float>; // Horizontal visual scaling on thing. Default = 1.0.
scaley = <float>; // Vertical visual scaling on thing. Default = 1.0.
scale = <float>; // Vertical and horizontal visual scaling on thing. Default = 1.0.
mobjscale = <float>; // Physical scale of the thing. Default = 1.0.
type = <integer>; // Thing type. No valid default.
flip = <bool>; // Thing spawns flipped, on the ceiling.
absolutez = <bool>; // If true, the thing height is absolute, instead of being relative to the floor or ceiling.
arg0 = <integer>; // Argument 0. Default = 0.
arg1 = <integer>; // Argument 1. Default = 0.
arg2 = <integer>; // Argument 2. Default = 0.
arg3 = <integer>; // Argument 3. Default = 0.
arg4 = <integer>; // Argument 4. Default = 0.
arg5 = <integer>; // Argument 5. Default = 0.
arg6 = <integer>; // Argument 6. Default = 0.
arg7 = <integer>; // Argument 7. Default = 0.
arg8 = <integer>; // Argument 8. Default = 0.
arg9 = <integer>; // Argument 9. Default = 0.
stringarg0 = <string>; // String argument 0.
stringarg1 = <string>; // String argument 1.
comment = <string>; // A comment. Implementors should attach no special
// semantic meaning to this field.
}
=======================================
Changelog
=======================================
1.0: 19.02.2024
Initial version.
===============================================================================
EOF
===============================================================================

View file

@ -154,6 +154,10 @@ if (UNIX)
target_compile_definitions(SRB2SDL2 PRIVATE -DUNIXCOMMON)
endif()
if (BSD MATCHES "FreeBSD")
target_compile_definitions(SRB2SDL2 PRIVATE -DFREEBSD)
endif()
if(CMAKE_COMPILER_IS_GNUCC)
find_program(OBJCOPY objcopy)
endif()

View file

@ -120,7 +120,7 @@ static void CONS_backcolor_Change(void);
#ifdef macintosh
#define CON_BUFFERSIZE 4096 // my compiler can't handle local vars >32k
#else
#define CON_BUFFERSIZE 16384
#define CON_BUFFERSIZE 32768
#endif
static char con_buffer[CON_BUFFERSIZE];

View file

@ -96,6 +96,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#endif
#if defined (__unix__) || (defined (UNIXCOMMON) && !defined (__APPLE__))
#include <poll.h>
#include <errno.h>
#include <sys/wait.h>
#define NEWSIGNALHANDLER
@ -855,50 +856,60 @@ static void I_GetConsoleEvents(void)
// we use this when sending back commands
event_t ev = {0};
char key = 0;
ssize_t d;
struct pollfd pfd =
{
.fd = STDIN_FILENO,
.events = POLLIN,
.revents = 0,
};
if (!consolevent)
return;
ev.type = ev_console;
ev.key = 0;
if (read(STDIN_FILENO, &key, 1) == -1 || !key)
return;
for (;;)
{
if (poll(&pfd, 1, 0) < 1 || !(pfd.revents & POLLIN))
return;
// we have something
// backspace?
// NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere
if ((key == tty_erase) || (key == 127) || (key == 8))
{
if (tty_con.cursor > 0)
ev.type = ev_console;
ev.key = 0;
if (read(STDIN_FILENO, &key, 1) == -1 || !key)
return;
// we have something
// backspace?
// NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere
if ((key == tty_erase) || (key == 127) || (key == 8))
{
tty_con.cursor--;
tty_con.buffer[tty_con.cursor] = '\0';
tty_Back();
if (tty_con.cursor > 0)
{
tty_con.cursor--;
tty_con.buffer[tty_con.cursor] = '\0';
tty_Back();
}
ev.key = KEY_BACKSPACE;
}
ev.key = KEY_BACKSPACE;
}
else if (key < ' ') // check if this is a control char
{
if (key == '\n')
else if (key < ' ') // check if this is a control char
{
tty_Clear();
tty_con.cursor = 0;
ev.key = KEY_ENTER;
if (key == '\n')
{
tty_Clear();
tty_con.cursor = 0;
ev.key = KEY_ENTER;
}
else continue;
}
else return;
else if (tty_con.cursor < sizeof(tty_con.buffer))
{
// push regular character
ev.key = tty_con.buffer[tty_con.cursor] = key;
tty_con.cursor++;
// print the current line (this is differential)
write(STDOUT_FILENO, &key, 1);
}
if (ev.key) D_PostEvent(&ev);
//tty_FlushIn();
}
else if (tty_con.cursor < sizeof(tty_con.buffer))
{
// push regular character
ev.key = tty_con.buffer[tty_con.cursor] = key;
tty_con.cursor++;
// print the current line (this is differential)
d = write(STDOUT_FILENO, &key, 1);
}
if (ev.key) D_PostEvent(&ev);
//tty_FlushIn();
(void)d;
}
#elif defined (_WIN32)

View file

@ -244,12 +244,12 @@ extern char logfilename[1024];
#define MAXPLAYERNAME 21
#define PLAYERSMASK (MAXPLAYERS-1)
// Don't make MAXSKINS higher than 256, since skin numbers are used with an
// UINT8 in various parts of the codebase. If you do anyway, the data type
// of those variables will have to be changed into at least an UINT16.
// Don't make MAXSKINS higher than 255, since skin numbers are used with an UINT8 in
// various parts of the codebase, and one number is reserved. If you do anyway,
// the data type of those variables will have to be changed into at least an UINT16.
// This change must affect code such as demo recording and playback,
// and the structure of some networking packets and commands.
#define MAXSKINS 256
#define MAXSKINS 255
#define MAXCHARACTERSLOTS (MAXSKINS * 3) // Should be higher than MAXSKINS.
#define COLORRAMPSIZE 16
@ -552,7 +552,7 @@ void *M_Memcpy(void* dest, const void* src, size_t n);
char *va(const char *format, ...) FUNCPRINTF;
char *M_GetToken(const char *inputString);
void M_UnGetToken(void);
void M_TokenizerOpen(const char *inputString);
void M_TokenizerOpen(const char *inputString, size_t len);
void M_TokenizerClose(void);
const char *M_TokenizerRead(UINT32 i);
const char *M_TokenizerReadZDoom(UINT32 i);

View file

@ -297,7 +297,7 @@ static void F_NewCutscene(const char *basetext)
cutscene_basetext = basetext;
memset(cutscene_disptext,0,sizeof(cutscene_disptext));
cutscene_writeptr = cutscene_baseptr = 0;
cutscene_textspeed = 9;
cutscene_textspeed = 8;
cutscene_textcount = TICRATE/2;
}
@ -313,22 +313,22 @@ const char *introtext[NUMINTROSCENES];
static tic_t introscenetime[NUMINTROSCENES] =
{
5*TICRATE, // STJr Presents
11*TICRATE + (TICRATE/2), // Two months had passed since...
15*TICRATE + (TICRATE/2), // As it was about to drain the rings...
14*TICRATE, // What Sonic, Tails, and Knuckles...
18*TICRATE, // About once every year, a strange...
19*TICRATE + (TICRATE/2), // Curses! Eggman yelled. That ridiculous...
19*TICRATE + (TICRATE/4), // It was only later that he had an idea...
10*TICRATE + (TICRATE/2), // Before beginning his scheme, Eggman decided to give Sonic...
16*TICRATE, // We're ready to fire in 15 seconds, the robot said...
16*TICRATE, // Meanwhile, Sonic was tearing across the zones...
10*TICRATE + (TICRATE/2), // Two months had passed since...
12*TICRATE + ((TICRATE/4) * 3), // As it was about to drain the rings...
12*TICRATE + (TICRATE/4), // What Sonic, Tails, and Knuckles...
16*TICRATE, // About once every year, a strange...
20*TICRATE + (TICRATE/2), // Curses! Eggman yelled. That ridiculous...
18*TICRATE + (TICRATE/4), // It was only later that he had an idea...
9*TICRATE + (TICRATE/2), // Before beginning his scheme, Eggman decided to give Sonic...
14*TICRATE, // We're ready to fire in 15 seconds, the robot said...
14*TICRATE + (TICRATE/2), // Meanwhile, Sonic was tearing across the zones...
16*TICRATE + (TICRATE/2), // Sonic knew he was getting closer to the city...
17*TICRATE, // Greenflower City was gone...
7*TICRATE, // You're not quite as dead as we thought, huh?...
11*TICRATE + (TICRATE/2), // Greenflower City was gone...
8*TICRATE, // You're not quite as dead as we thought, huh?...
8*TICRATE, // We'll see... let's give you a quick warm up...
18*TICRATE + (TICRATE/2), // Eggman took this as his cue and blasted off...
16*TICRATE, // Easy! We go find Eggman and stop his...
25*TICRATE, // I'm just finding what mission obje...
15*TICRATE, // Easy! We go find Eggman and stop his...
23*TICRATE, // I'm just finding what mission obje...
};
// custom intros
@ -1281,6 +1281,9 @@ void F_CreditDrawer(void)
UINT8 colornum;
const UINT8 *colormap;
// compensation for y on non-green resolutions, used to prevent text from disappearing before reaching the top
UINT16 compy = (vid.height - (BASEVIDHEIGHT * vid.dup)) / 2;
if (players[consoleplayer].skincolor)
colornum = players[consoleplayer].skincolor;
else
@ -1312,17 +1315,17 @@ void F_CreditDrawer(void)
y += 80<<FRACBITS;
break;
case 1:
if (y>>FRACBITS > -20)
if (y>>FRACBITS > -20-compy)
V_DrawCreditString((160 - (V_CreditStringWidth(&credits[i][1])>>1))<<FRACBITS, y, 0, &credits[i][1]);
y += 30<<FRACBITS;
break;
case 2:
if (y>>FRACBITS > -10)
if (y>>FRACBITS > -10-compy)
V_DrawStringAtFixed((BASEVIDWIDTH-V_StringWidth(&credits[i][1], V_ALLOWLOWERCASE|V_YELLOWMAP))<<FRACBITS>>1, y, V_ALLOWLOWERCASE|V_YELLOWMAP, &credits[i][1]);
y += 12<<FRACBITS;
break;
default:
if (y>>FRACBITS > -10)
if (y>>FRACBITS > -10-compy)
V_DrawStringAtFixed(32<<FRACBITS, y, V_ALLOWLOWERCASE, credits[i]);
y += 12<<FRACBITS;
break;

View file

@ -569,7 +569,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
if (rendermode == render_opengl)
{
// send in the wipe type and wipe frame because we need to cache the graphic
HWR_DoTintedWipe(wipetype, wipeframe-1);
HWR_DoWipe(wipetype, wipeframe-1);
}
else
#endif

View file

@ -10,5 +10,6 @@ target_sources(SRB2SDL2 PRIVATE
hw_md3load.c
hw_model.c
hw_batching.c
hw_shaders.c
r_opengl/r_opengl.c
)

View file

@ -9,4 +9,5 @@ hw_md2load.c
hw_md3load.c
hw_model.c
hw_batching.c
hw_shaders.c
r_opengl/r_opengl.c

View file

@ -76,7 +76,7 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture)
// If batching is enabled, this function collects the polygon data and the chosen texture
// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to
// render the polygon immediately.
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial)
void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader_target, boolean horizonSpecial)
{
if (currently_batching)
{
@ -114,7 +114,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
polygonArray[polygonArraySize].numVerts = iNumPts;
polygonArray[polygonArraySize].polyFlags = PolyFlags;
polygonArray[polygonArraySize].texture = current_texture;
polygonArray[polygonArraySize].shader = shader;
polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
// default to polygonArraySize so we don't lose order on horizon lines
// (yes, it's supposed to be negative, since we're sorting in that direction)
@ -134,7 +134,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
DIGEST(hash, pSurf->PolyColor.rgba);
if (cv_glshaders.value && gl_shadersavailable)
{
DIGEST(hash, shader);
DIGEST(hash, shader_target);
DIGEST(hash, pSurf->TintColor.rgba);
DIGEST(hash, pSurf->FadeColor.rgba);
DIGEST(hash, pSurf->LightInfo.light_level);
@ -151,10 +151,9 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
}
else
{
if (shader)
HWD.pfnSetShader(shader);
HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
}
HWD.pfnSetShader((shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target);
HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags);
}
}
static int comparePolygons(const void *p1, const void *p2)

View file

@ -32,6 +32,14 @@
INT32 patchformat = GL_TEXFMT_AP_88; // use alpha for holes
INT32 textureformat = GL_TEXFMT_P_8; // use chromakey for hole
RGBA_t mapPalette[256] = {0}; // the palette for the currently loaded level or menu etc.
// Returns a pointer to the palette which should be used for caching textures.
RGBA_t *HWR_GetTexturePalette(void)
{
return HWR_ShouldUsePaletteRendering() ? mapPalette : pLocalPalette;
}
static INT32 format2bpp(GLTextureFormat_t format)
{
if (format == GL_TEXFMT_RGBA)
@ -49,7 +57,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
INT32 pblockheight, INT32 blockmodulo,
fixed_t yfracstep, fixed_t scale_y,
texpatch_t *originPatch, INT32 patchheight,
INT32 bpp)
INT32 bpp, RGBA_t *palette)
{
fixed_t yfrac, position, count;
UINT8 *dest;
@ -113,7 +121,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3:
colortemp = V_GetColor(texel);
colortemp = palette[texel];
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
@ -123,7 +131,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
break;
case 4:
colortemp = V_GetColor(texel);
colortemp = palette[texel];
colortemp.s.alpha = alpha;
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
@ -152,7 +160,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
INT32 pblockheight, INT32 blockmodulo,
fixed_t yfracstep, fixed_t scale_y,
texpatch_t *originPatch, INT32 patchheight,
INT32 bpp)
INT32 bpp, RGBA_t *palette)
{
fixed_t yfrac, position, count;
UINT8 *dest;
@ -217,7 +225,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
memcpy(dest, &texelu16, sizeof(UINT16));
break;
case 3:
colortemp = V_GetColor(texel);
colortemp = palette[texel];
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
RGBA_t rgbatexel;
@ -227,7 +235,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8));
break;
case 4:
colortemp = V_GetColor(texel);
colortemp = palette[texel];
colortemp.s.alpha = alpha;
if ((originPatch != NULL) && (originPatch->style != AST_COPY))
{
@ -269,10 +277,13 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
UINT8 *block = mipmap->data;
INT32 bpp;
INT32 blockmodulo;
RGBA_t *palette;
if (pwidth <= 0 || pheight <= 0)
return;
palette = HWR_GetTexturePalette();
ncols = pwidth;
// source advance
@ -298,7 +309,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap,
pblockheight, blockmodulo,
yfracstep, scale_y,
NULL, pheight, // not that pheight is going to get used anyway...
bpp);
bpp, palette);
}
}
@ -317,16 +328,19 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
INT32 bpp;
INT32 blockmodulo;
INT32 width, height;
RGBA_t *palette;
// Column drawing function pointer.
static void (*ColumnDrawerPointer)(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap,
INT32 pblockheight, INT32 blockmodulo,
fixed_t yfracstep, fixed_t scale_y,
texpatch_t *originPatch, INT32 patchheight,
INT32 bpp);
INT32 bpp, RGBA_t *palette);
if (texture->width <= 0 || texture->height <= 0)
return;
palette = HWR_GetTexturePalette();
ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache;
x1 = patch->originx;
@ -386,7 +400,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
pblockheight, blockmodulo,
yfracstep, scale_y,
patch, height,
bpp);
bpp, palette);
}
}
@ -429,6 +443,9 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
INT32 i;
boolean skyspecial = false; //poor hack for Legacy large skies..
RGBA_t *palette;
palette = HWR_GetTexturePalette();
texture = textures[texnum];
// hack the Legacy skies..
@ -447,7 +464,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
grtex->mipmap.width = (UINT16)texture->width;
grtex->mipmap.height = (UINT16)texture->height;
grtex->mipmap.format = textureformat;
if (skyspecial)
grtex->mipmap.format = GL_TEXFMT_RGBA; // that skyspecial code below assumes this format ...
else
grtex->mipmap.format = textureformat;
blockwidth = texture->width;
blockheight = texture->height;
@ -459,7 +479,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex)
INT32 j;
RGBA_t col;
col = V_GetColor(HWR_PATCHES_CHROMAKEY_COLORINDEX);
col = palette[HWR_PATCHES_CHROMAKEY_COLORINDEX];
for (j = 0; j < blockheight; j++)
{
for (i = 0; i < blockwidth; i++)
@ -739,19 +759,6 @@ void HWR_LoadMapTextures(size_t pnumtextures)
gl_maptexturesloaded = true;
}
void HWR_SetPalette(RGBA_t *palette)
{
HWD.pfnSetPalette(palette);
// hardware driver will flush there own cache if cache is non paletized
// now flush data texture cache so 32 bit texture are recomputed
if (patchformat == GL_TEXFMT_RGBA || textureformat == GL_TEXFMT_RGBA)
{
Z_FreeTag(PU_HWRCACHE);
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
}
}
// --------------------------------------------------------------------------
// Make sure texture is downloaded and set it as the source
// --------------------------------------------------------------------------
@ -823,18 +830,13 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum)
void HWR_GetLevelFlat(levelflat_t *levelflat)
{
if (levelflat->type == LEVELFLAT_NONE)
if (levelflat->type == LEVELFLAT_NONE || levelflat->texture_id < 0)
{
HWR_SetCurrentTexture(NULL);
return;
}
INT32 texturenum = texturetranslation[levelflat->texture_id];
if (texturenum <= 0)
{
HWR_SetCurrentTexture(NULL);
return;
}
GLMapTexture_t *grtex = &gl_flats[texturenum];
GLMipmap_t *grMipmap = &grtex->mipmap;
@ -970,6 +972,139 @@ void HWR_UnlockCachedPatch(GLPatch_t *gpatch)
Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED);
}
static const INT32 picmode2GR[] =
{
GL_TEXFMT_P_8, // PALETTE
0, // INTENSITY (unsupported yet)
GL_TEXFMT_ALPHA_INTENSITY_88, // INTENSITY_ALPHA (corona use this)
0, // RGB24 (unsupported yet)
GL_TEXFMT_RGBA, // RGBA32 (opengl only)
};
static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheight,
INT32 blockmodulo, pic_t *pic, INT32 bpp)
{
INT32 i,j;
fixed_t posx, posy, stepx, stepy;
UINT8 *dest, *src, texel;
UINT16 texelu16;
INT32 picbpp;
RGBA_t col;
RGBA_t *palette = HWR_GetTexturePalette();
stepy = ((INT32)SHORT(pic->height)<<FRACBITS)/pblockheight;
stepx = ((INT32)SHORT(pic->width)<<FRACBITS)/pblockwidth;
picbpp = format2bpp(picmode2GR[pic->mode]);
posy = 0;
for (j = 0; j < pblockheight; j++)
{
posx = 0;
dest = &block[j*blockmodulo];
src = &pic->data[(posy>>FRACBITS)*SHORT(pic->width)*picbpp];
for (i = 0; i < pblockwidth;i++)
{
switch (pic->mode)
{ // source bpp
case PALETTE :
texel = src[(posx+FRACUNIT/2)>>FRACBITS];
switch (bpp)
{ // destination bpp
case 1 :
*dest++ = texel; break;
case 2 :
texelu16 = (UINT16)(texel | 0xff00);
memcpy(dest, &texelu16, sizeof(UINT16));
dest += sizeof(UINT16);
break;
case 3 :
col = palette[texel];
memcpy(dest, &col, sizeof(RGBA_t)-sizeof(UINT8));
dest += sizeof(RGBA_t)-sizeof(UINT8);
break;
case 4 :
memcpy(dest, &palette[texel], sizeof(RGBA_t));
dest += sizeof(RGBA_t);
break;
}
break;
case INTENSITY :
*dest++ = src[(posx+FRACUNIT/2)>>FRACBITS];
break;
case INTENSITY_ALPHA : // assume dest bpp = 2
memcpy(dest, src + ((posx+FRACUNIT/2)>>FRACBITS)*sizeof(UINT16), sizeof(UINT16));
dest += sizeof(UINT16);
break;
case RGB24 :
break; // not supported yet
case RGBA32 : // assume dest bpp = 4
dest += sizeof(UINT32);
memcpy(dest, src + ((posx+FRACUNIT/2)>>FRACBITS)*sizeof(UINT32), sizeof(UINT32));
break;
}
posx += stepx;
}
posy += stepy;
}
}
// -----------------+
// HWR_GetPic : Download a Doom pic (raw row encoded with no 'holes')
// Returns :
// -----------------+
patch_t *HWR_GetPic(lumpnum_t lumpnum)
{
patch_t *patch = HWR_GetCachedGLPatch(lumpnum);
GLPatch_t *grPatch = (GLPatch_t *)(patch->hardware);
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{
pic_t *pic;
UINT8 *block;
size_t len;
pic = W_CacheLumpNum(lumpnum, PU_CACHE);
patch->width = SHORT(pic->width);
patch->height = SHORT(pic->height);
len = W_LumpLength(lumpnum) - sizeof (pic_t);
grPatch->mipmap->width = (UINT16)patch->width;
grPatch->mipmap->height = (UINT16)patch->height;
if (pic->mode == PALETTE)
grPatch->mipmap->format = textureformat; // can be set by driver
else
grPatch->mipmap->format = picmode2GR[pic->mode];
Z_Free(grPatch->mipmap->data);
// allocate block
block = MakeBlock(grPatch->mipmap);
if (patch->width == SHORT(pic->width) &&
patch->height == SHORT(pic->height) &&
format2bpp(grPatch->mipmap->format) == format2bpp(picmode2GR[pic->mode]))
{
// no conversion needed
M_Memcpy(grPatch->mipmap->data, pic->data,len);
}
else
HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height),
SHORT(pic->width)*format2bpp(grPatch->mipmap->format),
pic,
format2bpp(grPatch->mipmap->format));
Z_Unlock(pic);
Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED);
grPatch->mipmap->flags = 0;
grPatch->max_s = grPatch->max_t = 1.0f;
}
HWD.pfnSetTexture(grPatch->mipmap);
//CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grPatch->mipmap->data, grPatch->mipmap->downloaded);
return patch;
}
patch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum)
{
lumpcache_t *lumpcache = wadfiles[wadnum]->patchcache;
@ -997,6 +1132,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
UINT8 *flat;
UINT8 *dest, *src, texel;
RGBA_t col;
RGBA_t *palette = HWR_GetTexturePalette();
// Place the flats data into flat
W_ReadLump(fademasklumpnum, Z_Malloc(W_LumpLength(fademasklumpnum),
@ -1014,7 +1150,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32
{
// fademask bpp is always 1, and is used just for alpha
texel = src[(posx)>>FRACBITS];
col = V_GetColor(texel);
col = palette[texel];
*dest = col.s.red; // take the red level of the colour and use it for alpha, as fademasks do
dest++;
@ -1086,4 +1222,185 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum)
Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED);
}
// =================================================
// PALETTE HANDLING
// =================================================
void HWR_SetPalette(RGBA_t *palette)
{
if (HWR_ShouldUsePaletteRendering())
{
// set the palette for palette postprocessing
if (cv_glpalettedepth.value == 16)
{
// crush to 16-bit rgb565, like software currently does in the standard configuration
// Note: Software's screenshots have the 24-bit palette, but the screen gets
// the 16-bit version! For making comparison screenshots either use an external screenshot
// tool or set the palette depth to 24 bits.
RGBA_t crushed_palette[256];
int i;
for (i = 0; i < 256; i++)
{
float fred = (float)(palette[i].s.red >> 3);
float fgreen = (float)(palette[i].s.green >> 2);
float fblue = (float)(palette[i].s.blue >> 3);
crushed_palette[i].s.red = (UINT8)(fred / 31.0f * 255.0f);
crushed_palette[i].s.green = (UINT8)(fgreen / 63.0f * 255.0f);
crushed_palette[i].s.blue = (UINT8)(fblue / 31.0f * 255.0f);
crushed_palette[i].s.alpha = 255;
}
HWD.pfnSetScreenPalette(crushed_palette);
}
else
{
HWD.pfnSetScreenPalette(palette);
}
// this part is responsible for keeping track of the palette OUTSIDE of a level.
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
HWR_SetMapPalette();
}
else
{
// set the palette for the textures
HWD.pfnSetTexturePalette(palette);
// reset mapPalette so next call to HWR_SetMapPalette will update everything correctly
memset(mapPalette, 0, sizeof(mapPalette));
// hardware driver will flush there own cache if cache is non paletized
// now flush data texture cache so 32 bit texture are recomputed
if (patchformat == GL_TEXFMT_RGBA || textureformat == GL_TEXFMT_RGBA)
{
Z_FreeTag(PU_HWRCACHE);
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
}
}
}
static void HWR_SetPaletteLookup(RGBA_t *palette)
{
int r, g, b;
UINT8 *lut = Z_Malloc(
HWR_PALETTE_LUT_SIZE*HWR_PALETTE_LUT_SIZE*HWR_PALETTE_LUT_SIZE*sizeof(UINT8),
PU_STATIC, NULL);
#define STEP_SIZE (256/HWR_PALETTE_LUT_SIZE)
for (b = 0; b < HWR_PALETTE_LUT_SIZE; b++)
{
for (g = 0; g < HWR_PALETTE_LUT_SIZE; g++)
{
for (r = 0; r < HWR_PALETTE_LUT_SIZE; r++)
{
lut[b*HWR_PALETTE_LUT_SIZE*HWR_PALETTE_LUT_SIZE+g*HWR_PALETTE_LUT_SIZE+r] =
NearestPaletteColor(r*STEP_SIZE, g*STEP_SIZE, b*STEP_SIZE, palette);
}
}
}
#undef STEP_SIZE
HWD.pfnSetPaletteLookup(lut);
Z_Free(lut);
}
// Updates mapPalette to reflect the loaded level or other game state.
// Textures are flushed if needed.
// Call this function only in palette rendering mode.
void HWR_SetMapPalette(void)
{
RGBA_t RGBA_converted[256];
RGBA_t *palette;
int i;
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
{
// outside of a level, pMasterPalette should have PLAYPAL ready for us
palette = pMasterPalette;
}
else
{
// in a level pMasterPalette might have a flash palette, but we
// want the map's original palette.
lumpnum_t lumpnum = W_GetNumForName(GetPalette());
size_t palsize = W_LumpLength(lumpnum);
UINT8 *RGB_data;
if (palsize < 768) // 256 * 3
I_Error("HWR_SetMapPalette: A programmer assumed palette lumps are at least 768 bytes long, but apparently this was a wrong assumption!\n");
RGB_data = W_CacheLumpNum(lumpnum, PU_CACHE);
// we got the RGB palette now, but we need it in RGBA format.
for (i = 0; i < 256; i++)
{
RGBA_converted[i].s.red = *(RGB_data++);
RGBA_converted[i].s.green = *(RGB_data++);
RGBA_converted[i].s.blue = *(RGB_data++);
RGBA_converted[i].s.alpha = 255;
}
palette = RGBA_converted;
}
// check if the palette has changed from the previous one
if (memcmp(mapPalette, palette, sizeof(mapPalette)))
{
memcpy(mapPalette, palette, sizeof(mapPalette));
// in palette rendering mode, this means that all rgba textures now have wrong colors
// and the lookup table is outdated
HWR_SetPaletteLookup(mapPalette);
HWD.pfnSetTexturePalette(mapPalette);
if (patchformat == GL_TEXFMT_RGBA || textureformat == GL_TEXFMT_RGBA)
{
Z_FreeTag(PU_HWRCACHE);
Z_FreeTag(PU_HWRCACHE_UNLOCKED);
}
}
}
// Creates a hardware lighttable from the supplied lighttable.
// Returns the id of the hw lighttable, usable in FSurfaceInfo.
UINT32 HWR_CreateLightTable(UINT8 *lighttable)
{
UINT32 i, id;
RGBA_t *palette = HWR_GetTexturePalette();
RGBA_t *hw_lighttable = Z_Malloc(256 * 32 * sizeof(RGBA_t), PU_STATIC, NULL);
// To make the palette index -> RGBA mapping easier for the shader,
// the hardware lighttable is composed of RGBA colors instead of palette indices.
for (i = 0; i < 256 * 32; i++)
hw_lighttable[i] = palette[lighttable[i]];
id = HWD.pfnCreateLightTable(hw_lighttable);
Z_Free(hw_lighttable);
return id;
}
// get hwr lighttable id for colormap, create it if it doesn't already exist
UINT32 HWR_GetLightTableID(extracolormap_t *colormap)
{
boolean default_colormap = false;
if (!colormap)
{
colormap = R_GetDefaultColormap(); // a place to store the hw lighttable id
// alternatively could just store the id in a global variable if there are issues
default_colormap = true;
}
// create hw lighttable if there isn't one
if (!colormap->gl_lighttable_id)
{
UINT8 *colormap_pointer;
if (default_colormap)
colormap_pointer = colormaps; // don't actually use the data from the "default colormap"
else
colormap_pointer = colormap->colormap;
colormap->gl_lighttable_id = HWR_CreateLightTable(colormap_pointer);
}
return colormap->gl_lighttable_id;
}
// Note: all hardware lighttable ids assigned before this
// call become invalid and must not be used.
void HWR_ClearLightTables(void)
{
if (vid.glstate == VID_GL_LIBRARY_LOADED)
HWD.pfnClearLightTables();
}
#endif //HWRENDER

View file

@ -18,6 +18,12 @@
#define ZCLIP_PLANE 4.0f // Used for the actual game drawing
#define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures
// The width/height/depth of the palette lookup table used by palette rendering.
// Changing this also requires changing the shader code!
// Also assumed to be a power of two in some parts of the code.
// 64 seems to work perfectly for the vanilla palette.
#define HWR_PALETTE_LUT_SIZE 64
// ==========================================================================
// SIMPLE TYPES
// ==========================================================================
@ -122,33 +128,31 @@ typedef struct
} FOutVector;
#ifdef GL_SHADERS
// Predefined shader types
// Shader targets used to render specific types of geometry.
// A shader target is resolved to an actual shader with HWR_GetShaderFromTarget.
// The shader returned may be a base shader or a custom shader.
enum
{
SHADER_NONE = -1,
SHADER_DEFAULT = 0,
SHADER_FLOOR,
SHADER_FLOOR = 0,
SHADER_WALL,
SHADER_SPRITE,
SHADER_MODEL, SHADER_MODEL_LIGHTING,
SHADER_MODEL,
SHADER_WATER,
SHADER_FOG,
SHADER_SKY,
SHADER_PALETTE_POSTPROCESS,
SHADER_UI_COLORMAP_FADE,
SHADER_UI_TINTED_WIPE,
NUMBASESHADERS,
NUMSHADERTARGETS
};
// Maximum amount of shader programs
// Must be higher than NUMBASESHADERS
#define HWR_MAXSHADERS 16
// Shader sources (vertex and fragment)
typedef struct
{
char *vertex;
char *fragment;
} shadersource_t;
// Must be at least NUMSHADERTARGETS*2 to fit base and custom shaders for each shader target.
#define HWR_MAXSHADERS NUMSHADERTARGETS*2
// Custom shader reference table
typedef struct
@ -272,11 +276,15 @@ struct FSurfaceInfo
RGBA_t PolyColor;
RGBA_t TintColor;
RGBA_t FadeColor;
UINT32 LightTableId;
FLightInfo LightInfo;
};
typedef struct FSurfaceInfo FSurfaceInfo;
//Hurdler: added for backward compatibility
#define GL_DEFAULTMIX 0x00000000
#define GL_DEFAULTFOG 0xFF000000
// Various settings and states for the rendering backend.
enum hwdsetspecialstate
{
HWD_SET_MODEL_LIGHTING = 1,
@ -289,15 +297,13 @@ enum hwdsetspecialstate
typedef enum hwdsetspecialstate hwdspecialstate_t;
// Lactozilla: Shader options
enum hwdshaderoption
enum hwdshaderstage
{
HWD_SHADEROPTION_OFF,
HWD_SHADEROPTION_ON,
HWD_SHADEROPTION_NOCUSTOM,
HWD_SHADERSTAGE_VERTEX,
HWD_SHADERSTAGE_FRAGMENT,
};
typedef enum hwdshaderoption hwdshaderoption_t;
typedef enum hwdshaderstage hwdshaderstage_t;
// Lactozilla: Shader info
// Generally set at the start of the frame.
@ -318,5 +324,18 @@ enum hwdfiltermode
HWD_SET_TEXTUREFILTER_MIXED3,
};
// Screen texture slots
enum hwdscreentexture
{
HWD_SCREENTEXTURE_WIPE_START, // source image for the wipe/fade effect
HWD_SCREENTEXTURE_WIPE_END, // destination image for the wipe/fade effect
HWD_SCREENTEXTURE_GENERIC1, // underwater/heat effect, intermission background
HWD_SCREENTEXTURE_GENERIC2, // palette-based colormap fade, screen before palette rendering's postprocessing
HWD_SCREENTEXTURE_GENERIC3, // screen after palette rendering's postprocessing
NUMSCREENTEXTURES, // (generic3 is unused if palette rendering is disabled)
};
typedef enum hwdscreentexture hwdscreentexture_t;
#endif //_HWR_DEFS_

View file

@ -30,6 +30,7 @@
#include "../st_stuff.h"
#include "../p_local.h" // stplyr
#include "../g_game.h" // players
#include "../f_finale.h" // fade color factors
#include <fcntl.h>
#include "../i_video.h" // for rendermode != render_glide
@ -707,6 +708,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
{
FOutVector v[4];
FSurfaceInfo Surf;
FBITFIELD poly_flags = PF_NoTexture|PF_Modulated|PF_NoDepthTest;
v[0].x = v[3].x = -1.0f;
v[2].x = v[1].x = 1.0f;
@ -719,17 +721,59 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
v[0].t = v[1].t = 1.0f;
v[2].t = v[3].t = 0.0f;
if (color & 0xFF00) // Do COLORMAP fade.
if (color & 0xFF00) // Special fade options
{
Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
Surf.PolyColor.s.alpha = (strength*8);
UINT16 option = color & 0x0F00;
if (option == 0x0A00 || option == 0x0B00) // Tinted fades
{
INT32 r, g, b;
int fade = strength * 8;
r = FADEREDFACTOR*fade/10;
g = FADEGREENFACTOR*fade/10;
b = FADEBLUEFACTOR*fade/10;
Surf.PolyColor.s.red = min(r, 255);
Surf.PolyColor.s.green = min(g, 255);
Surf.PolyColor.s.blue = min(b, 255);
Surf.PolyColor.s.alpha = 255;
if (option == 0x0A00) // Tinted subtractive fade
poly_flags |= PF_ReverseSubtract;
else if (option == 0x0B00) // Tinted additive fade
poly_flags |= PF_Additive;
}
else // COLORMAP fade
{
if (HWR_ShouldUsePaletteRendering())
{
const hwdscreentexture_t scr_tex = HWD_SCREENTEXTURE_GENERIC2;
Surf.LightTableId = HWR_GetLightTableID(NULL);
Surf.LightInfo.light_level = strength;
HWD.pfnMakeScreenTexture(scr_tex);
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_UI_COLORMAP_FADE));
HWD.pfnDrawScreenTexture(scr_tex, &Surf, PF_ColorMapped|PF_NoDepthTest);
HWD.pfnUnSetShader();
return;
}
else
{
Surf.PolyColor.rgba = UINT2RGBA(0x01010160);
Surf.PolyColor.s.alpha = (strength*8);
poly_flags |= PF_Translucent;
}
}
}
else // Do TRANSMAP** fade.
{
Surf.PolyColor.rgba = V_GetColor(color).rgba;
RGBA_t *palette = HWR_GetTexturePalette();
Surf.PolyColor.rgba = palette[color&0xFF].rgba;
Surf.PolyColor.s.alpha = softwaretranstogl[strength];
poly_flags |= PF_Translucent;
}
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
HWD.pfnDrawPolygon(&Surf, v, 4, poly_flags);
}
// -----------------+
@ -897,7 +941,8 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac
}
else // Do TRANSMAP** fade.
{
Surf.PolyColor.rgba = V_GetColor(actualcolor).rgba;
RGBA_t *palette = HWR_GetTexturePalette();
Surf.PolyColor.rgba = palette[actualcolor&0xFF].rgba;
Surf.PolyColor.s.alpha = softwaretranstogl[strength];
}
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
@ -1102,8 +1147,9 @@ void HWR_drawAMline(const fline_t *fl, INT32 color)
{
F2DCoord v1, v2;
RGBA_t color_rgba;
RGBA_t *palette = HWR_GetTexturePalette();
color_rgba = V_GetColor(color);
color_rgba = palette[color&0xFF];
v1.x = ((float)fl->a.x-(vid.width/2.0f))*(2.0f/vid.width);
v1.y = ((float)fl->a.y-(vid.height/2.0f))*(2.0f/vid.height);
@ -1288,6 +1334,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
FOutVector v[4];
FSurfaceInfo Surf;
float fx, fy, fw, fh;
RGBA_t *palette = HWR_GetTexturePalette();
UINT8 alphalevel = ((color & V_ALPHAMASK) >> V_ALPHASHIFT);
UINT8 perplayershuffle = 0;
@ -1374,7 +1421,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
{
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
{
RGBA_t rgbaColour = V_GetColor(color);
RGBA_t rgbaColour = palette[color&0xFF];
FRGBAFloat clearColour;
clearColour.red = (float)rgbaColour.s.red / 255;
clearColour.green = (float)rgbaColour.s.green / 255;
@ -1451,7 +1498,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
v[0].t = v[1].t = 0.0f;
v[2].t = v[3].t = 1.0f;
Surf.PolyColor = V_GetColor(color);
Surf.PolyColor = palette[color&0xFF];
if (alphalevel)
{
@ -1539,11 +1586,12 @@ static inline boolean saveTGA(const char *file_name, void *buffer,
UINT8 *HWR_GetScreenshot(void)
{
UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf));
int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2;
if (!buf)
return NULL;
// returns 24bit 888 RGB
HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf);
HWD.pfnReadScreenTexture(tex, (void *)buf);
return buf;
}
@ -1551,6 +1599,7 @@ boolean HWR_Screenshot(const char *pathname)
{
boolean ret;
UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf));
int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2;
if (!buf)
{
@ -1559,7 +1608,7 @@ boolean HWR_Screenshot(const char *pathname)
}
// returns 24bit 888 RGB
HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf);
HWD.pfnReadScreenTexture(tex, (void *)buf);
#ifdef USE_PNG
ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL);

View file

@ -32,7 +32,7 @@ EXPORT void HWRAPI(Shutdown) (void);
#ifdef _WINDOWS
EXPORT void HWRAPI(GetModeList) (vmode_t **pvidmodes, INT32 *numvidmodes);
#endif
EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal);
EXPORT void HWRAPI(SetTexturePalette) (RGBA_t *ppal);
EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl);
EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
@ -43,11 +43,10 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFl
EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *TexInfo);
EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data);
EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT8 *dst_data);
EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip);
EXPORT void HWRAPI(ClearMipMapCache) (void);
//Hurdler: added for backward compatibility
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development
@ -57,24 +56,26 @@ EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
EXPORT void HWRAPI(FlushScreenTextures) (void);
EXPORT void HWRAPI(StartScreenWipe) (void);
EXPORT void HWRAPI(EndScreenWipe) (void);
EXPORT void HWRAPI(DoScreenWipe) (void);
EXPORT void HWRAPI(DrawIntermissionBG) (void);
EXPORT void HWRAPI(MakeScreenTexture) (void);
EXPORT void HWRAPI(MakeScreenFinalTexture) (void);
EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height);
EXPORT void HWRAPI(DoScreenWipe) (int wipeStart, int wipeEnd, FSurfaceInfo *surf, FBITFIELD polyFlags);
EXPORT void HWRAPI(DrawScreenTexture) (int tex, FSurfaceInfo *surf, FBITFIELD polyflags);
EXPORT void HWRAPI(MakeScreenTexture) (int tex);
EXPORT void HWRAPI(DrawScreenFinalTexture) (int tex, int width, int height);
#define SCREENVERTS 10
EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]);
EXPORT boolean HWRAPI(CompileShaders) (void);
EXPORT void HWRAPI(CleanShaders) (void);
EXPORT void HWRAPI(SetShader) (int type);
EXPORT boolean HWRAPI(InitShaders) (void);
EXPORT void HWRAPI(LoadShader) (int slot, char *code, hwdshaderstage_t stage);
EXPORT boolean HWRAPI(CompileShader) (int slot);
EXPORT void HWRAPI(SetShader) (int slot);
EXPORT void HWRAPI(UnSetShader) (void);
EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment);
EXPORT void HWRAPI(SetPaletteLookup)(UINT8 *lut);
EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable);
EXPORT void HWRAPI(ClearLightTables)(void);
EXPORT void HWRAPI(SetScreenPalette)(RGBA_t *palette);
// ==========================================================================
// HWR DRIVER OBJECT, FOR CLIENT PROGRAM
@ -85,7 +86,7 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boole
struct hwdriver_s
{
Init pfnInit;
SetPalette pfnSetPalette;
SetTexturePalette pfnSetTexturePalette;
FinishUpdate pfnFinishUpdate;
Draw2DLine pfnDraw2DLine;
DrawPolygon pfnDrawPolygon;
@ -96,10 +97,10 @@ struct hwdriver_s
SetTexture pfnSetTexture;
UpdateTexture pfnUpdateTexture;
DeleteTexture pfnDeleteTexture;
ReadRect pfnReadRect;
ReadScreenTexture pfnReadScreenTexture;
GClipRect pfnGClipRect;
ClearMipMapCache pfnClearMipMapCache;
SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility
SetSpecialState pfnSetSpecialState;
DrawModel pfnDrawModel;
CreateModelVBOs pfnCreateModelVBOs;
SetTransform pfnSetTransform;
@ -112,21 +113,23 @@ struct hwdriver_s
#endif
PostImgRedraw pfnPostImgRedraw;
FlushScreenTextures pfnFlushScreenTextures;
StartScreenWipe pfnStartScreenWipe;
EndScreenWipe pfnEndScreenWipe;
DoScreenWipe pfnDoScreenWipe;
DrawIntermissionBG pfnDrawIntermissionBG;
DrawScreenTexture pfnDrawScreenTexture;
MakeScreenTexture pfnMakeScreenTexture;
MakeScreenFinalTexture pfnMakeScreenFinalTexture;
DrawScreenFinalTexture pfnDrawScreenFinalTexture;
CompileShaders pfnCompileShaders;
CleanShaders pfnCleanShaders;
InitShaders pfnInitShaders;
LoadShader pfnLoadShader;
CompileShader pfnCompileShader;
SetShader pfnSetShader;
UnSetShader pfnUnSetShader;
SetShaderInfo pfnSetShaderInfo;
LoadCustomShader pfnLoadCustomShader;
SetPaletteLookup pfnSetPaletteLookup;
CreateLightTable pfnCreateLightTable;
ClearLightTables pfnClearLightTables;
SetScreenPalette pfnSetScreenPalette;
};
extern struct hwdriver_s hwdriver;

View file

@ -107,6 +107,8 @@ void HWR_FreeExtraSubsectors(void);
// --------
// hw_cache.c
// --------
RGBA_t *HWR_GetTexturePalette(void);
void HWR_InitMapTextures(void);
void HWR_LoadMapTextures(size_t pnumtextures);
void HWR_FreeMapTextures(void);
@ -131,6 +133,10 @@ void HWR_FreeColormapCache(void);
void HWR_UnlockCachedPatch(GLPatch_t *gpatch);
void HWR_SetPalette(RGBA_t *palette);
void HWR_SetMapPalette(void);
UINT32 HWR_CreateLightTable(UINT8 *lighttable);
UINT32 HWR_GetLightTableID(extracolormap_t *colormap);
void HWR_ClearLightTables(void);
// --------
@ -139,4 +145,18 @@ void HWR_SetPalette(RGBA_t *palette);
extern INT32 patchformat;
extern INT32 textureformat;
// --------
// hw_shaders.c
// --------
boolean HWR_InitShaders(void);
void HWR_CompileShaders(void);
int HWR_GetShaderFromTarget(int shader_target);
void HWR_LoadAllCustomShaders(void);
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3);
const char *HWR_GetShaderName(INT32 shader);
extern customshaderxlat_t shaderxlat[];
#endif //_HW_GLOB_

View file

@ -130,26 +130,6 @@ static line_t *gl_linedef;
static sector_t *gl_frontsector;
static sector_t *gl_backsector;
// --------------------------------------------------------------------------
// STUFF FOR THE PROJECTION CODE
// --------------------------------------------------------------------------
FTransform atransform;
// duplicates of the main code, set after R_SetupFrame() passed them into sharedstruct,
// copied here for local use
static fixed_t dup_viewx, dup_viewy, dup_viewz;
static angle_t dup_viewangle;
static float gl_viewx, gl_viewy, gl_viewz;
float gl_viewsin, gl_viewcos;
// Maybe not necessary with the new T&L code (needs to be checked!)
static float gl_viewludsin, gl_viewludcos; // look up down kik test
static float gl_fovlud;
static angle_t gl_aimingangle;
static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox);
// Render stats
ps_metric_t ps_hw_skyboxtime = {0};
ps_metric_t ps_hw_nodesorttime = {0};
@ -170,13 +150,39 @@ ps_metric_t ps_hw_batchdrawtime = {0};
boolean gl_init = false;
boolean gl_maploaded = false;
boolean gl_shadersavailable = true;
boolean gl_sessioncommandsadded = false;
// false if shaders have not been initialized yet, or if shaders are not available
boolean gl_shadersavailable = false;
// Whether the internal state is set to palette rendering or not.
static boolean gl_palette_rendering_state = false;
// --------------------------------------------------------------------------
// STUFF FOR THE PROJECTION CODE
// --------------------------------------------------------------------------
FTransform atransform;
// duplicates of the main code, set after R_SetupFrame() passed them into sharedstruct,
// copied here for local use
static fixed_t dup_viewx, dup_viewy, dup_viewz;
static angle_t dup_viewangle;
static float gl_viewx, gl_viewy, gl_viewz;
float gl_viewsin, gl_viewcos;
// Maybe not necessary with the new T&L code (needs to be checked!)
static float gl_viewludsin, gl_viewludcos; // look up down kik test
static float gl_fovlud;
static angle_t gl_aimingangle;
static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox);
// ==========================================================================
// Lighting
// ==========================================================================
static boolean HWR_UseShader(void)
// Returns true if shaders can be used.
boolean HWR_UseShader(void)
{
return (cv_glshaders.value && gl_shadersavailable);
}
@ -242,6 +248,11 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col
Surface->LightInfo.light_level = light_level;
Surface->LightInfo.fade_start = (colormap != NULL) ? colormap->fadestart : 0;
Surface->LightInfo.fade_end = (colormap != NULL) ? colormap->fadeend : 31;
if (HWR_ShouldUsePaletteRendering())
Surface->LightTableId = HWR_GetLightTableID(colormap);
else
Surface->LightTableId = 0;
}
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if this can work
@ -372,7 +383,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
FOutVector *v3d;
polyvertex_t *pv;
pslope_t *slope = NULL;
INT32 shader = SHADER_DEFAULT;
INT32 shader = SHADER_NONE;
size_t nrPlaneVerts;
INT32 i;
@ -533,6 +544,9 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
PolyFlags |= PF_ColorMapped;
}
if (!cv_renderfloors.value)
return;
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false);
if (subsector)
@ -759,7 +773,10 @@ static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, I
//
static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap)
{
INT32 shader = SHADER_DEFAULT;
INT32 shader = SHADER_NONE;
if (!cv_renderwalls.value)
return;
HWR_Lighting(pSurf, lightlevel, wallcolormap);
@ -834,6 +851,9 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y);
extracolormap_t *colormap = NULL;
if (!cv_renderwalls.value)
return;
realtop = top = wallVerts[3].y;
realbot = bot = wallVerts[0].y;
diff = top - bot;
@ -872,13 +892,15 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
{
if (pfloor && (pfloor->fofflags & FOF_FOG))
{
lightnum = HWR_CalcWallLight(pfloor->master->frontsector->lightlevel, v1x, v1y, v2x, v2y);
lightnum = pfloor->master->frontsector->lightlevel;
colormap = pfloor->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
}
else
{
lightnum = HWR_CalcWallLight(*list[i].lightlevel, v1x, v1y, v2x, v2y);
lightnum = *list[i].lightlevel;
colormap = *list[i].extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
}
}
@ -1109,8 +1131,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
float cliplow = (float)texturehpeg;
float cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT));
FUINT lightnum = HWR_CalcWallLight(gl_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
FUINT lightnum = gl_frontsector->lightlevel;
extracolormap_t *colormap = gl_frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
FSurfaceInfo Surf;
Surf.PolyColor.s.alpha = 255;
@ -1705,8 +1728,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
blendmode = PF_Fog|PF_NoTexture;
lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
lightnum = rover->master->frontsector->lightlevel;
colormap = rover->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap);
@ -1827,8 +1851,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
blendmode = PF_Fog|PF_NoTexture;
lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
lightnum = rover->master->frontsector->lightlevel;
colormap = rover->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap);
@ -2694,7 +2719,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
{
FSurfaceInfo Surf;
FOutVector *v3d;
INT32 shader = SHADER_DEFAULT;
INT32 shader = SHADER_NONE;
size_t nrPlaneVerts = polysector->numVertices;
INT32 i;
@ -3527,7 +3552,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
float fscale; float fx; float fy; float offset;
extracolormap_t *colormap = NULL;
FBITFIELD blendmode = PF_Translucent|PF_Modulated;
INT32 shader = SHADER_DEFAULT;
INT32 shader = SHADER_NONE;
UINT8 i;
INT32 heightsec, phs;
SINT8 flip = P_MobjFlip(thing);
@ -3735,7 +3760,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
boolean lightset = true;
FBITFIELD blend = 0;
FBITFIELD occlusion;
INT32 shader = SHADER_DEFAULT;
INT32 shader = SHADER_NONE;
boolean use_linkdraw_hack = false;
UINT8 alpha;
@ -4306,7 +4331,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
}
{
INT32 shader = SHADER_DEFAULT;
INT32 shader = SHADER_NONE;
FBITFIELD blend = 0;
FBITFIELD occlusion;
boolean use_linkdraw_hack = false;
@ -4380,7 +4405,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
// Sprite drawer for precipitation
static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
{
INT32 shader = SHADER_DEFAULT;
INT32 shader = SHADER_NONE;
FBITFIELD blend = 0;
FOutVector wallVerts[4];
patch_t *gpatch;
@ -4825,7 +4850,6 @@ static void HWR_CreateDrawNodes(void)
// Okay! Let's draw it all! Woo!
HWD.pfnSetTransform(&atransform);
HWD.pfnSetShader(SHADER_DEFAULT);
for (i = 0; i < p; i++)
{
@ -5058,6 +5082,9 @@ static void HWR_ProjectSprite(mobj_t *thing)
// uncapped/interpolation
interpmobjstate_t interp = {0};
if (!cv_renderthings.value)
return;
if (!thing)
return;
@ -5884,7 +5911,8 @@ static void HWR_DrawSkyBackground(player_t *player)
HWR_BuildSkyDome();
}
HWD.pfnSetShader(SHADER_SKY); // sky shader
if (HWR_UseShader())
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_SKY));
HWD.pfnSetTransform(&dometransform);
HWD.pfnRenderSkyDome(&gl_sky);
}
@ -5970,8 +5998,6 @@ static void HWR_DrawSkyBackground(player_t *player)
HWD.pfnUnSetShader();
HWD.pfnDrawPolygon(NULL, v, 4, 0);
}
HWD.pfnSetShader(SHADER_DEFAULT);
}
@ -6061,13 +6087,7 @@ static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean
//
static void HWR_SetShaderState(void)
{
hwdshaderoption_t state = cv_glshaders.value;
if (!cv_glallowshaders.value)
state = (cv_glshaders.value == HWD_SHADEROPTION_ON ? HWD_SHADEROPTION_NOCUSTOM : cv_glshaders.value);
HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)state);
HWD.pfnSetShader(SHADER_DEFAULT);
HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)HWR_UseShader());
}
// ==========================================================================
@ -6083,6 +6103,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
else
type = &postimgtype;
if (!HWR_ShouldUsePaletteRendering())
{
// do we really need to save player (is it not the same)?
player_t *saved_player = stplyr;
@ -6275,6 +6296,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind
PS_STOP_TIMING(ps_hw_skyboxtime);
if (!HWR_ShouldUsePaletteRendering())
{
// do we really need to save player (is it not the same)?
player_t *saved_player = stplyr;
@ -6451,6 +6473,56 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE);
}
// Returns whether palette rendering is "actually enabled."
// Can't have palette rendering if shaders are disabled.
boolean HWR_ShouldUsePaletteRendering(void)
{
return (cv_glpaletterendering.value && HWR_UseShader());
}
// enable or disable palette rendering state depending on settings and availability
// called when relevant settings change
// shader recompilation is done in the cvar callback
static void HWR_TogglePaletteRendering(void)
{
// which state should we go to?
if (HWR_ShouldUsePaletteRendering())
{
// are we not in that state already?
if (!gl_palette_rendering_state)
{
gl_palette_rendering_state = true;
// The textures will still be converted to RGBA by r_opengl.
// This however makes hw_cache use paletted blending for composite textures!
// (patchformat is not touched)
textureformat = GL_TEXFMT_P_8;
HWR_SetMapPalette();
HWR_SetPalette(pLocalPalette);
// If the r_opengl "texture palette" stays the same during this switch, these textures
// will not be cleared out. However they are still out of date since the
// composite texture blending method has changed. Therefore they need to be cleared.
HWR_LoadMapTextures(numtextures);
}
}
else
{
// are we not in that state already?
if (gl_palette_rendering_state)
{
gl_palette_rendering_state = false;
textureformat = GL_TEXFMT_RGBA;
HWR_SetPalette(pLocalPalette);
// If the r_opengl "texture palette" stays the same during this switch, these textures
// will not be cleared out. However they are still out of date since the
// composite texture blending method has changed. Therefore they need to be cleared.
HWR_LoadMapTextures(numtextures);
}
}
}
void HWR_LoadLevel(void)
{
#ifdef ALAM_LIGHTING
@ -6464,6 +6536,9 @@ void HWR_LoadLevel(void)
HWR_ClearSkyDome();
HWR_BuildSkyDome();
if (HWR_ShouldUsePaletteRendering())
HWR_SetMapPalette();
gl_maploaded = true;
}
@ -6471,13 +6546,17 @@ void HWR_LoadLevel(void)
// 3D ENGINE COMMANDS
// ==========================================================================
static CV_PossibleValue_t glshaders_cons_t[] = {{HWD_SHADEROPTION_OFF, "Off"}, {HWD_SHADEROPTION_ON, "On"}, {HWD_SHADEROPTION_NOCUSTOM, "Ignore custom shaders"}, {0, NULL}};
static CV_PossibleValue_t glshaders_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Ignore custom shaders"}, {0, NULL}};
static CV_PossibleValue_t glmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}};
static CV_PossibleValue_t glfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}};
static CV_PossibleValue_t glshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}};
static void CV_glfiltermode_OnChange(void);
static void CV_glanisotropic_OnChange(void);
static void CV_glmodellighting_OnChange(void);
static void CV_glpaletterendering_OnChange(void);
static void CV_glpalettedepth_OnChange(void);
static void CV_glshaders_OnChange(void);
static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"},
{HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"},
@ -6487,7 +6566,7 @@ static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA
{0, NULL}};
CV_PossibleValue_t glanisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}};
consvar_t cv_glshaders = CVAR_INIT ("gr_shaders", "On", CV_SAVE, glshaders_cons_t, NULL);
consvar_t cv_glshaders = CVAR_INIT ("gr_shaders", "On", CV_SAVE|CV_CALL, glshaders_cons_t, CV_glshaders_OnChange);
#ifdef ALAM_LIGHTING
consvar_t cv_gldynamiclighting = CVAR_INIT ("gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL);
@ -6498,7 +6577,7 @@ consvar_t cv_glcoronasize = CVAR_INIT ("gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0
consvar_t cv_glmodels = CVAR_INIT ("gr_models", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glmodelinterpolation = CVAR_INIT ("gr_modelinterpolation", "Sometimes", CV_SAVE, glmodelinterpolation_cons_t, NULL);
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_glmodellighting_OnChange);
consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, glshearing_cons_t, NULL);
consvar_t cv_glspritebillboarding = CVAR_INIT ("gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL);
@ -6513,18 +6592,61 @@ consvar_t cv_glsolvetjoin = CVAR_INIT ("gr_solvetjoin", "On", 0, CV_OnOff, NULL)
consvar_t cv_glbatching = CVAR_INIT ("gr_batching", "On", 0, CV_OnOff, NULL);
static CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 bits"}, {0, NULL}};
consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletterendering", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_glpaletterendering_OnChange);
consvar_t cv_glpalettedepth = CVAR_INIT ("gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_glpalettedepth_OnChange);
#define ONLY_IF_GL_LOADED if (vid.glstate != VID_GL_LIBRARY_LOADED) return;
consvar_t cv_glwireframe = CVAR_INIT ("gr_wireframe", "Off", 0, CV_OnOff, NULL);
static void CV_glfiltermode_OnChange(void)
{
if (rendermode == render_opengl)
HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value);
ONLY_IF_GL_LOADED
HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value);
}
static void CV_glanisotropic_OnChange(void)
{
if (rendermode == render_opengl)
HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value);
ONLY_IF_GL_LOADED
HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value);
}
static void CV_glmodellighting_OnChange(void)
{
ONLY_IF_GL_LOADED
// if shaders have been compiled, then they now need to be recompiled.
if (gl_shadersavailable)
HWR_CompileShaders();
}
static void CV_glpaletterendering_OnChange(void)
{
ONLY_IF_GL_LOADED
if (gl_shadersavailable)
{
HWR_CompileShaders();
HWR_TogglePaletteRendering();
}
}
static void CV_glpalettedepth_OnChange(void)
{
ONLY_IF_GL_LOADED
// refresh the screen palette
if (HWR_ShouldUsePaletteRendering())
HWR_SetPalette(pLocalPalette);
}
static void CV_glshaders_OnChange(void)
{
ONLY_IF_GL_LOADED
HWR_SetShaderState();
if (cv_glpaletterendering.value)
{
// can't do palette rendering without shaders, so update the state if needed
HWR_TogglePaletteRendering();
}
}
//added by Hurdler: console varibale that are saved
@ -6553,6 +6675,8 @@ void HWR_AddCommands(void)
CV_RegisterVar(&cv_glbatching);
CV_RegisterVar(&cv_glpaletterendering);
CV_RegisterVar(&cv_glpalettedepth);
CV_RegisterVar(&cv_glwireframe);
#ifndef NEWCLIP
@ -6569,6 +6693,8 @@ void HWR_Startup(void)
{
CONS_Printf("HWR_Startup()...\n");
textureformat = patchformat = GL_TEXFMT_RGBA;
HWR_InitPolyPool();
HWR_InitMapTextures();
HWR_InitModels();
@ -6576,14 +6702,12 @@ void HWR_Startup(void)
HWR_InitLight();
#endif
gl_shadersavailable = HWR_InitShaders();
HWR_SetShaderState();
HWR_LoadAllCustomShaders();
if (!HWR_CompileShaders())
gl_shadersavailable = false;
HWR_TogglePaletteRendering();
}
if (rendermode == render_opengl)
textureformat = patchformat = GL_TEXFMT_RGBA;
gl_init = true;
}
@ -6647,6 +6771,9 @@ void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 te
{
static size_t allocedwalls = 0;
if (!cv_renderwalls.value)
return;
// Force realloc if buffer has been freed
if (!wallinfo)
allocedwalls = 0;
@ -6673,7 +6800,10 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
FBITFIELD blendmode = blend;
UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha
INT32 shader = SHADER_DEFAULT;
INT32 shader = SHADER_NONE;
if (!cv_renderwalls.value)
return;
// Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting
HWR_Lighting(pSurf, lightlevel, wallcolormap);
@ -6718,7 +6848,7 @@ void HWR_DoPostProcessor(player_t *player)
// Armageddon Blast Flash!
// Could this even be considered postprocessor?
if (player->flashcount)
if (player->flashcount && !HWR_ShouldUsePaletteRendering())
{
FOutVector v[4];
FSurfaceInfo Surf;
@ -6743,7 +6873,7 @@ void HWR_DoPostProcessor(player_t *player)
// Capture the screen for intermission and screen waving
if(gamestate != GS_INTERMISSION)
HWD.pfnMakeScreenTexture();
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
if (splitscreen) // Not supported in splitscreen - someone want to add support?
return;
@ -6787,7 +6917,7 @@ void HWR_DoPostProcessor(player_t *player)
// Capture the screen again for screen waving on the intermission
if(gamestate != GS_INTERMISSION)
HWD.pfnMakeScreenTexture();
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
}
// Flipping of the screen isn't done here anymore
}
@ -6795,18 +6925,18 @@ void HWR_DoPostProcessor(player_t *player)
void HWR_StartScreenWipe(void)
{
//CONS_Debug(DBG_RENDER, "In HWR_StartScreenWipe()\n");
HWD.pfnStartScreenWipe();
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_WIPE_START);
}
void HWR_EndScreenWipe(void)
{
//CONS_Debug(DBG_RENDER, "In HWR_EndScreenWipe()\n");
HWD.pfnEndScreenWipe();
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_WIPE_END);
}
void HWR_DrawIntermissionBG(void)
{
HWD.pfnDrawIntermissionBG();
HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC1, NULL, 0);
}
//
@ -6851,201 +6981,40 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum)
return;
HWR_GetFadeMask(wipelumpnum);
HWD.pfnDoScreenWipe();
}
if (wipestyle == WIPESTYLE_COLORMAP && HWR_UseShader())
{
FSurfaceInfo surf = {0};
FBITFIELD polyflags = PF_Modulated|PF_NoDepthTest;
void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum)
{
// It does the same thing
HWR_DoWipe(wipenum, scrnnum);
polyflags |= (wipestyleflags & WSF_TOWHITE) ? PF_Additive : PF_ReverseSubtract;
surf.PolyColor.s.red = FADEREDFACTOR;
surf.PolyColor.s.green = FADEGREENFACTOR;
surf.PolyColor.s.blue = FADEBLUEFACTOR;
// polycolor alpha communicates fadein / fadeout to the shader and the backend
surf.PolyColor.s.alpha = (wipestyleflags & WSF_FADEIN) ? 255 : 0;
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_UI_TINTED_WIPE));
HWD.pfnDoScreenWipe(HWD_SCREENTEXTURE_WIPE_START, HWD_SCREENTEXTURE_WIPE_END,
&surf, polyflags);
HWD.pfnUnSetShader();
}
else
{
HWD.pfnDoScreenWipe(HWD_SCREENTEXTURE_WIPE_START, HWD_SCREENTEXTURE_WIPE_END,
NULL, 0);
}
}
void HWR_MakeScreenFinalTexture(void)
{
HWD.pfnMakeScreenFinalTexture();
int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2;
HWD.pfnMakeScreenTexture(tex);
}
void HWR_DrawScreenFinalTexture(int width, int height)
{
HWD.pfnDrawScreenFinalTexture(width, height);
}
static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum)
{
UINT16 i;
lumpinfo_t *lump_p;
lump_p = wadfiles[wadnum]->lumpinfo;
for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++)
if (memcmp(lump_p->name, "SHADERS", 7) == 0)
return i;
return INT16_MAX;
}
boolean HWR_CompileShaders(void)
{
return HWD.pfnCompileShaders();
}
customshaderxlat_t shaderxlat[] =
{
{"Flat", SHADER_FLOOR},
{"WallTexture", SHADER_WALL},
{"Sprite", SHADER_SPRITE},
{"Model", SHADER_MODEL},
{"ModelLighting", SHADER_MODEL_LIGHTING},
{"WaterRipple", SHADER_WATER},
{"Fog", SHADER_FOG},
{"Sky", SHADER_SKY},
{NULL, 0},
};
void HWR_LoadAllCustomShaders(void)
{
INT32 i;
// read every custom shader
for (i = 0; i < numwadfiles; i++)
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
}
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
{
UINT16 lump;
char *shaderdef, *line;
char *stoken;
char *value;
size_t size;
int linenum = 1;
int shadertype = 0;
int i;
lump = HWR_FindShaderDefs(wadnum);
if (lump == INT16_MAX)
return;
shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
size = W_LumpLengthPwad(wadnum, lump);
line = Z_Malloc(size+1, PU_STATIC, NULL);
M_Memcpy(line, shaderdef, size);
line[size] = '\0';
stoken = strtok(line, "\r\n ");
while (stoken)
{
if ((stoken[0] == '/' && stoken[1] == '/')
|| (stoken[0] == '#'))// skip comments
{
stoken = strtok(NULL, "\r\n");
goto skip_field;
}
if (!stricmp(stoken, "GLSL"))
{
value = strtok(NULL, "\r\n ");
if (!value)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
stoken = strtok(NULL, "\r\n"); // skip end of line
goto skip_lump;
}
if (!stricmp(value, "VERTEX"))
shadertype = 1;
else if (!stricmp(value, "FRAGMENT"))
shadertype = 2;
skip_lump:
stoken = strtok(NULL, "\r\n ");
linenum++;
}
else
{
value = strtok(NULL, "\r\n= ");
if (!value)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
stoken = strtok(NULL, "\r\n"); // skip end of line
goto skip_field;
}
if (!shadertype)
{
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
Z_Free(line);
return;
}
for (i = 0; shaderxlat[i].type; i++)
{
if (!stricmp(shaderxlat[i].type, stoken))
{
size_t shader_size;
char *shader_source;
char *shader_lumpname;
UINT16 shader_lumpnum;
if (PK3)
{
shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL);
strcpy(shader_lumpname, "Shaders/sh_");
strcat(shader_lumpname, value);
shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0);
}
else
{
shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL);
strcpy(shader_lumpname, "SH_");
strcat(shader_lumpname, value);
shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0);
}
if (shader_lumpnum == INT16_MAX)
{
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum);
Z_Free(shader_lumpname);
continue;
}
shader_size = W_LumpLengthPwad(wadnum, shader_lumpnum);
shader_source = Z_Malloc(shader_size, PU_STATIC, NULL);
W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source);
HWD.pfnLoadCustomShader(shaderxlat[i].id, shader_source, shader_size, (shadertype == 2));
Z_Free(shader_source);
Z_Free(shader_lumpname);
}
}
skip_field:
stoken = strtok(NULL, "\r\n= ");
linenum++;
}
}
Z_Free(line);
return;
}
const char *HWR_GetShaderName(INT32 shader)
{
INT32 i;
if (shader)
{
for (i = 0; shaderxlat[i].type; i++)
{
if (shaderxlat[i].id == shader)
return shaderxlat[i].type;
}
return "Unknown";
}
return "Default";
int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2;
HWD.pfnDrawScreenFinalTexture(tex, width, height);
}
#endif // HWRENDER

View file

@ -61,11 +61,11 @@ void HWR_StartScreenWipe(void);
void HWR_EndScreenWipe(void);
void HWR_DrawIntermissionBG(void);
void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum);
void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum);
void HWR_MakeScreenFinalTexture(void);
void HWR_DrawScreenFinalTexture(int width, int height);
// This stuff is put here so models can use them
boolean HWR_UseShader(void);
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap);
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work
@ -74,13 +74,7 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 style);
FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
boolean HWR_CompileShaders(void);
void HWR_LoadAllCustomShaders(void);
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3);
const char *HWR_GetShaderName(INT32 shader);
extern customshaderxlat_t shaderxlat[];
boolean HWR_ShouldUsePaletteRendering(void);
extern CV_PossibleValue_t glanisotropicmode_cons_t[];
@ -103,8 +97,9 @@ extern consvar_t cv_glspritebillboarding;
extern consvar_t cv_glskydome;
extern consvar_t cv_glfakecontrast;
extern consvar_t cv_glslopecontrast;
extern consvar_t cv_glbatching;
extern consvar_t cv_glpaletterendering;
extern consvar_t cv_glpalettedepth;
extern consvar_t cv_glwireframe;

View file

@ -390,8 +390,6 @@ static void md2_loadTexture(md2_t *model)
if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data)
{
int w = 0, h = 0;
UINT32 size;
RGBA_t *image;
#ifdef HAVE_PNG
grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch);
@ -412,13 +410,19 @@ static void md2_loadTexture(md2_t *model)
grPatch->mipmap->width = (UINT16)w;
grPatch->mipmap->height = (UINT16)h;
// Lactozilla: Apply colour cube
image = grPatch->mipmap->data;
size = w*h;
while (size--)
// for palette rendering, color cube is applied in post-processing instead of here
if (!HWR_ShouldUsePaletteRendering())
{
V_CubeApply(&image->s.red, &image->s.green, &image->s.blue);
image++;
UINT32 size;
RGBA_t *image;
// Lactozilla: Apply colour cube
image = grPatch->mipmap->data;
size = w*h;
while (size--)
{
V_CubeApply(&image->s.red, &image->s.green, &image->s.blue);
image++;
}
}
}
HWD.pfnSetTexture(grPatch->mipmap);
@ -1550,7 +1554,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
p.flip = atransform.flip;
p.mirror = atransform.mirror;
HWD.pfnSetShader(SHADER_MODEL); // model shader
if (HWR_UseShader())
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_MODEL));
{
float this_scale = FIXED_TO_FLOAT(interp.scale);

636
src/hardware/hw_shaders.c Normal file
View file

@ -0,0 +1,636 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2021 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file hw_shaders.c
/// \brief Handles the shaders used by the game.
#ifdef HWRENDER
#include "hw_glob.h"
#include "hw_drv.h"
#include "hw_shaders.h"
#include "../z_zone.h"
// ================
// Shader sources
// ================
static struct {
const char *vertex;
const char *fragment;
} const gl_shadersources[] = {
// Floor shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FLOOR_FRAGMENT_SHADER},
// Wall shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER},
// Sprite shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER},
// Model shader
{GLSL_MODEL_VERTEX_SHADER, GLSL_MODEL_FRAGMENT_SHADER},
// Water shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER},
// Fog shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER},
// Sky shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER},
// Palette postprocess shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER},
// UI colormap fade shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER},
// UI tinted wipe shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_UI_TINTED_WIPE_FRAGMENT_SHADER},
{NULL, NULL},
};
typedef struct
{
int base_shader; // index of base shader_t
int custom_shader; // index of custom shader_t
} shadertarget_t;
typedef struct
{
char *vertex;
char *fragment;
boolean compiled;
} shader_t; // these are in an array and accessed by indices
// the array has NUMSHADERTARGETS entries for base shaders and for custom shaders
// the array could be expanded in the future to fit "dynamic" custom shaders that
// aren't fixed to shader targets
static shader_t gl_shaders[NUMSHADERTARGETS*2];
static shadertarget_t gl_shadertargets[NUMSHADERTARGETS];
#define WHITESPACE_CHARS " \t"
#define MODEL_LIGHTING_DEFINE "#define SRB2_MODEL_LIGHTING"
#define PALETTE_RENDERING_DEFINE "#define SRB2_PALETTE_RENDERING"
// Initialize shader variables and the backend's shader system. Load the base shaders.
// Returns false if shaders cannot be used.
boolean HWR_InitShaders(void)
{
int i;
if (!HWD.pfnInitShaders())
return false;
for (i = 0; i < NUMSHADERTARGETS; i++)
{
// set up string pointers for base shaders
gl_shaders[i].vertex = Z_StrDup(gl_shadersources[i].vertex);
gl_shaders[i].fragment = Z_StrDup(gl_shadersources[i].fragment);
// set shader target indices to correct values
gl_shadertargets[i].base_shader = i;
gl_shadertargets[i].custom_shader = -1;
}
HWR_CompileShaders();
return true;
}
// helper function: strstr but returns an int with the substring position
// returns INT32_MAX if not found
static INT32 strstr_int(const char *str1, const char *str2)
{
char *location = strstr(str1, str2);
if (location)
return location - str1;
else
return INT32_MAX;
}
// Creates a preprocessed copy of the shader according to the current graphics settings
// Returns a pointer to the results on success and NULL on failure.
// Remember memory management of the returned string.
static char *HWR_PreprocessShader(char *original)
{
const char *line_ending = "\n";
int line_ending_len;
char *read_pos = original;
int original_len = strlen(original);
int distance_to_end = original_len;
int new_len;
char *new_shader;
char *write_pos;
char shader_glsl_version[3];
int version_pos = -1;
int version_len = 0;
if (strstr(original, "\r\n"))
{
line_ending = "\r\n";
// check if all line endings are same
while ((read_pos = strchr(read_pos, '\n')))
{
read_pos--;
if (*read_pos != '\r')
{
// this file contains mixed CRLF and LF line endings.
// treating it as a LF file during parsing should keep
// the results sane enough as long as the gpu driver is fine
// with these kinds of weirdly formatted shader sources.
line_ending = "\n";
break;
}
read_pos += 2;
}
read_pos = original;
}
line_ending_len = strlen(line_ending);
// Find the #version directive, if it exists. Also don't get fooled if it's
// inside a comment. Copy the version digits so they can be used in the preamble.
// Time for some string parsing :D
#define STARTSWITH(str, with_what) !strncmp(str, with_what, sizeof(with_what)-1)
#define ADVANCE(amount) read_pos += (amount); distance_to_end -= (amount);
while (true)
{
// we're at the start of a line or at the end of a block comment.
// first get any possible whitespace out of the way
int whitespace_len = strspn(read_pos, WHITESPACE_CHARS);
if (whitespace_len == distance_to_end)
break; // we got to the end
ADVANCE(whitespace_len)
if (STARTSWITH(read_pos, "#version"))
{
// found a version directive (and it's not inside a comment)
// now locate, verify and read the version number
int version_number_len;
version_pos = read_pos - original;
ADVANCE(sizeof("#version") - 1)
whitespace_len = strspn(read_pos, WHITESPACE_CHARS);
if (!whitespace_len)
{
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected space after #version, but got other text.\n");
return NULL;
}
else if (whitespace_len == distance_to_end)
{
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version number, but got end of file.\n");
return NULL;
}
ADVANCE(whitespace_len)
version_number_len = strspn(read_pos, "0123456789");
if (!version_number_len)
{
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version number, but got other text.\n");
return NULL;
}
else if (version_number_len != 3)
{
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version with 3 digits, but got %d digits.\n", version_number_len);
return NULL;
}
M_Memcpy(shader_glsl_version, read_pos, 3);
ADVANCE(version_number_len)
version_len = (read_pos - original) - version_pos;
whitespace_len = strspn(read_pos, WHITESPACE_CHARS);
ADVANCE(whitespace_len)
if (STARTSWITH(read_pos, "es"))
{
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Support for ES shaders is not implemented.\n");
return NULL;
}
break;
}
else
{
// go to next newline or end of next block comment if it starts before the newline
// and is not inside a line comment
INT32 newline_pos = strstr_int(read_pos, line_ending);
INT32 line_comment_pos;
INT32 block_comment_pos;
// optimization: temporarily put a null at the line ending, so strstr does not needlessly
// look past it since we're only interested in the current line
if (newline_pos != INT32_MAX)
read_pos[newline_pos] = '\0';
line_comment_pos = strstr_int(read_pos, "//");
block_comment_pos = strstr_int(read_pos, "/*");
// restore the line ending, remove the null we just put there
if (newline_pos != INT32_MAX)
read_pos[newline_pos] = line_ending[0];
if (line_comment_pos < block_comment_pos)
{
// line comment found, skip rest of the line
if (newline_pos != INT32_MAX)
{
ADVANCE(newline_pos + line_ending_len)
}
else
{
// we got to the end
break;
}
}
else if (block_comment_pos < line_comment_pos)
{
// block comment found, skip past it
INT32 block_comment_end;
ADVANCE(block_comment_pos + 2)
block_comment_end = strstr_int(read_pos, "*/");
if (block_comment_end == INT32_MAX)
{
// could also leave insertion_pos at 0 and let the GLSL compiler
// output an error message for this broken comment
CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Encountered unclosed block comment in shader.\n");
return NULL;
}
ADVANCE(block_comment_end + 2)
}
else if (newline_pos == INT32_MAX)
{
// we got to the end
break;
}
else
{
// nothing special on this line, move to the next one
ADVANCE(newline_pos + line_ending_len)
}
}
}
#undef STARTSWITH
#undef ADVANCE
#define ADD_TO_LEN(def) new_len += sizeof(def) - 1 + line_ending_len;
// Calculate length of modified shader.
new_len = original_len;
if (cv_glmodellighting.value)
ADD_TO_LEN(MODEL_LIGHTING_DEFINE)
if (cv_glpaletterendering.value)
ADD_TO_LEN(PALETTE_RENDERING_DEFINE)
#undef ADD_TO_LEN
#define VERSION_PART "#version "
if (new_len != original_len)
{
if (version_pos != -1)
new_len += sizeof(VERSION_PART) - 1 + 3 + line_ending_len;
new_len += sizeof("#line 0") - 1 + line_ending_len;
}
// Allocate memory for modified shader.
new_shader = Z_Malloc(new_len + 1, PU_STATIC, NULL);
read_pos = original;
write_pos = new_shader;
if (new_len != original_len && version_pos != -1)
{
strcpy(write_pos, VERSION_PART);
write_pos += sizeof(VERSION_PART) - 1;
M_Memcpy(write_pos, shader_glsl_version, 3);
write_pos += 3;
strcpy(write_pos, line_ending);
write_pos += line_ending_len;
}
#undef VERSION_PART
#define WRITE_DEFINE(define) \
{ \
strcpy(write_pos, define); \
write_pos += sizeof(define) - 1; \
strcpy(write_pos, line_ending); \
write_pos += line_ending_len; \
}
// Write the defines.
if (cv_glmodellighting.value)
WRITE_DEFINE(MODEL_LIGHTING_DEFINE)
if (cv_glpaletterendering.value)
WRITE_DEFINE(PALETTE_RENDERING_DEFINE)
#undef WRITE_DEFINE
// Write a #line directive, so compiler errors will report line numbers from the
// original shader without our preamble lines.
if (new_len != original_len)
{
// line numbering in the #line directive is different for versions 110-150
if (version_pos == -1 || shader_glsl_version[0] == '1')
strcpy(write_pos, "#line 0");
else
strcpy(write_pos, "#line 1");
write_pos += sizeof("#line 0") - 1;
strcpy(write_pos, line_ending);
write_pos += line_ending_len;
}
// Copy the original shader.
M_Memcpy(write_pos, read_pos, original_len);
// Erase the original #version directive, if it exists and was copied.
if (new_len != original_len && version_pos != -1)
memset(write_pos + version_pos, ' ', version_len);
// Terminate the new string.
new_shader[new_len] = '\0';
return new_shader;
}
// preprocess and compile shader at gl_shaders[index]
static void HWR_CompileShader(int index)
{
char *vertex_source = gl_shaders[index].vertex;
char *fragment_source = gl_shaders[index].fragment;
if (vertex_source)
{
char *preprocessed = HWR_PreprocessShader(vertex_source);
if (!preprocessed) return;
HWD.pfnLoadShader(index, preprocessed, HWD_SHADERSTAGE_VERTEX);
}
if (fragment_source)
{
char *preprocessed = HWR_PreprocessShader(fragment_source);
if (!preprocessed) return;
HWD.pfnLoadShader(index, preprocessed, HWD_SHADERSTAGE_FRAGMENT);
}
gl_shaders[index].compiled = HWD.pfnCompileShader(index);
}
// compile or recompile shaders
void HWR_CompileShaders(void)
{
int i;
for (i = 0; i < NUMSHADERTARGETS; i++)
{
int custom_index = gl_shadertargets[i].custom_shader;
HWR_CompileShader(i);
if (!gl_shaders[i].compiled)
CONS_Alert(CONS_ERROR, "HWR_CompileShaders: Compilation failed for base %s shader!\n", shaderxlat[i].type);
if (custom_index != -1)
{
HWR_CompileShader(custom_index);
if (!gl_shaders[custom_index].compiled)
CONS_Alert(CONS_ERROR, "HWR_CompileShaders: Recompilation failed for the custom %s shader! See the console messages above for more information.\n", shaderxlat[i].type);
}
}
}
int HWR_GetShaderFromTarget(int shader_target)
{
int custom_shader = gl_shadertargets[shader_target].custom_shader;
// use custom shader if following are true
// - custom shader exists
// - custom shader has been compiled successfully
// - custom shaders are enabled
// - custom shaders are allowed by the server
if (custom_shader != -1 && gl_shaders[custom_shader].compiled &&
cv_glshaders.value == 1 && cv_glallowshaders.value)
return custom_shader;
else
return gl_shadertargets[shader_target].base_shader;
}
static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum)
{
UINT16 i;
lumpinfo_t *lump_p;
lump_p = wadfiles[wadnum]->lumpinfo;
for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++)
if (memcmp(lump_p->name, "SHADERS", 7) == 0)
return i;
return INT16_MAX;
}
customshaderxlat_t shaderxlat[] =
{
{"Flat", SHADER_FLOOR},
{"WallTexture", SHADER_WALL},
{"Sprite", SHADER_SPRITE},
{"Model", SHADER_MODEL},
{"WaterRipple", SHADER_WATER},
{"Fog", SHADER_FOG},
{"Sky", SHADER_SKY},
{"PalettePostprocess", SHADER_PALETTE_POSTPROCESS},
{"UIColormapFade", SHADER_UI_COLORMAP_FADE},
{"UITintedWipe", SHADER_UI_TINTED_WIPE},
{NULL, 0},
};
void HWR_LoadAllCustomShaders(void)
{
INT32 i;
// read every custom shader
for (i = 0; i < numwadfiles; i++)
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
}
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
{
UINT16 lump;
char *shaderdef, *line;
char *stoken;
char *value;
size_t size;
int linenum = 1;
int shadertype = 0;
int i;
boolean modified_shaders[NUMSHADERTARGETS] = {0};
if (!gl_shadersavailable)
return;
lump = HWR_FindShaderDefs(wadnum);
if (lump == INT16_MAX)
return;
shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
size = W_LumpLengthPwad(wadnum, lump);
line = Z_Malloc(size+1, PU_STATIC, NULL);
M_Memcpy(line, shaderdef, size);
line[size] = '\0';
stoken = strtok(line, "\r\n ");
while (stoken)
{
if ((stoken[0] == '/' && stoken[1] == '/')
|| (stoken[0] == '#'))// skip comments
{
stoken = strtok(NULL, "\r\n");
goto skip_field;
}
if (!stricmp(stoken, "GLSL"))
{
value = strtok(NULL, "\r\n ");
if (!value)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
stoken = strtok(NULL, "\r\n"); // skip end of line
goto skip_lump;
}
if (!stricmp(value, "VERTEX"))
shadertype = 1;
else if (!stricmp(value, "FRAGMENT"))
shadertype = 2;
skip_lump:
stoken = strtok(NULL, "\r\n ");
linenum++;
}
else
{
value = strtok(NULL, "\r\n= ");
if (!value)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
stoken = strtok(NULL, "\r\n"); // skip end of line
goto skip_field;
}
if (!shadertype)
{
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum);
Z_Free(line);
return;
}
for (i = 0; shaderxlat[i].type; i++)
{
if (!stricmp(shaderxlat[i].type, stoken))
{
size_t shader_string_length;
char *shader_source;
char *shader_lumpname;
UINT16 shader_lumpnum;
int shader_index; // index in gl_shaders
if (PK3)
{
shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL);
strcpy(shader_lumpname, "Shaders/sh_");
strcat(shader_lumpname, value);
shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0);
}
else
{
shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL);
strcpy(shader_lumpname, "SH_");
strcat(shader_lumpname, value);
shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0);
}
if (shader_lumpnum == INT16_MAX)
{
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum);
Z_Free(shader_lumpname);
continue;
}
shader_string_length = W_LumpLengthPwad(wadnum, shader_lumpnum) + 1;
shader_source = Z_Malloc(shader_string_length, PU_STATIC, NULL);
W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source);
shader_source[shader_string_length-1] = '\0';
shader_index = shaderxlat[i].id + NUMSHADERTARGETS;
if (!modified_shaders[shaderxlat[i].id])
{
// this will clear any old custom shaders from previously loaded files
// Z_Free checks if the pointer is NULL!
Z_Free(gl_shaders[shader_index].vertex);
gl_shaders[shader_index].vertex = NULL;
Z_Free(gl_shaders[shader_index].fragment);
gl_shaders[shader_index].fragment = NULL;
}
modified_shaders[shaderxlat[i].id] = true;
if (shadertype == 1)
{
if (gl_shaders[shader_index].vertex)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s vertex shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
Z_Free(gl_shaders[shader_index].vertex);
}
gl_shaders[shader_index].vertex = shader_source;
}
else
{
if (gl_shaders[shader_index].fragment)
{
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s fragment shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum);
Z_Free(gl_shaders[shader_index].fragment);
}
gl_shaders[shader_index].fragment = shader_source;
}
Z_Free(shader_lumpname);
}
}
skip_field:
stoken = strtok(NULL, "\r\n= ");
linenum++;
}
}
for (i = 0; i < NUMSHADERTARGETS; i++)
{
if (modified_shaders[i])
{
int shader_index = i + NUMSHADERTARGETS; // index to gl_shaders
gl_shadertargets[i].custom_shader = shader_index;
// if only one stage (vertex/fragment) is defined, the other one
// is copied from the base shaders.
if (!gl_shaders[shader_index].fragment)
gl_shaders[shader_index].fragment = Z_StrDup(gl_shadersources[i].fragment);
if (!gl_shaders[shader_index].vertex)
gl_shaders[shader_index].vertex = Z_StrDup(gl_shadersources[i].vertex);
HWR_CompileShader(shader_index);
if (!gl_shaders[shader_index].compiled)
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename);
}
}
Z_Free(line);
return;
}
const char *HWR_GetShaderName(INT32 shader)
{
INT32 i;
for (i = 0; shaderxlat[i].type; i++)
{
if (shaderxlat[i].id == shader)
return shaderxlat[i].type;
}
return "Unknown";
}
#endif // HWRENDER

424
src/hardware/hw_shaders.h Normal file
View file

@ -0,0 +1,424 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2021 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file hw_shaders.h
/// \brief Handles the shaders used by the game.
#ifndef _HW_SHADERS_H_
#define _HW_SHADERS_H_
#include "../doomtype.h"
// ================
// Vertex shaders
// ================
//
// Generic vertex shader
//
#define GLSL_DEFAULT_VERTEX_SHADER \
"void main()\n" \
"{\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"gl_FrontColor = gl_Color;\n" \
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0"
// replicates the way fixed function lighting is used by the model lighting option,
// stores the lighting result to gl_Color
// (ambient lighting of 0.75 and diffuse lighting from above)
#define GLSL_MODEL_VERTEX_SHADER \
"void main()\n" \
"{\n" \
"#ifdef SRB2_MODEL_LIGHTING\n" \
"float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \
"float light = min(0.75 + max(nDotVP, 0.0), 1.0);\n" \
"gl_FrontColor = vec4(light, light, light, 1.0);\n" \
"#else\n" \
"gl_FrontColor = gl_Color;\n" \
"#endif\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0"
// ==================
// Fragment shaders
// ==================
//
// Generic fragment shader
//
#define GLSL_DEFAULT_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"void main(void) {\n" \
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
"}\0"
//
// Software fragment shader
//
// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro.
#define GLSL_DOOM_COLORMAP \
"float R_DoomColormap(float light, float z)\n" \
"{\n" \
"float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \
"float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \
"float startmap = (15.0 - lightnum) * 4.0;\n" \
"float scale = 160.0 / (lightz + 1.0);\n" \
"float cap = (155.0 - light) * 0.26;\n" \
"return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \
"}\n"
// lighting cap adjustment:
// first num (155.0), increase to make it start to go dark sooner
// second num (0.26), increase to make it go dark faster
#define GLSL_DOOM_LIGHT_EQUATION \
"float R_DoomLightingEquation(float light)\n" \
"{\n" \
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
"float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \
"return clamp(colormap, 0.0, 31.0) / 32.0;\n" \
"}\n"
#define GLSL_SOFTWARE_TINT_EQUATION \
"if (tint_color.a > 0.0) {\n" \
"float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \
"float strength = sqrt(tint_color.a);\n" \
"final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \
"final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \
"final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \
"}\n"
#define GLSL_SOFTWARE_FADE_EQUATION \
"float darkness = R_DoomLightingEquation(lighting);\n" \
"if (fade_start != 0.0 || fade_end != 31.0) {\n" \
"float fs = fade_start / 31.0;\n" \
"float fe = fade_end / 31.0;\n" \
"float fd = fe - fs;\n" \
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
"}\n" \
"final_color = mix(final_color, fade_color, darkness);\n"
#define GLSL_PALETTE_RENDERING \
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
"float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \
"vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
#define GLSL_SOFTWARE_FRAGMENT_SHADER \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"uniform sampler2D tex;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler2D lighttable_tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform float lighting;\n" \
GLSL_DOOM_COLORMAP \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
GLSL_PALETTE_RENDERING \
"}\n" \
"#else\n" \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\n" \
"#endif\0"
// hand tuned adjustments for light level calculation
#define GLSL_FLOOR_FUDGES \
"#define STARTMAP_FUDGE 1.06\n" \
"#define SCALE_FUDGE 1.15\n"
#define GLSL_WALL_FUDGES \
"#define STARTMAP_FUDGE 1.05\n" \
"#define SCALE_FUDGE 2.2\n"
#define GLSL_FLOOR_FRAGMENT_SHADER \
GLSL_FLOOR_FUDGES \
GLSL_SOFTWARE_FRAGMENT_SHADER
#define GLSL_WALL_FRAGMENT_SHADER \
GLSL_WALL_FUDGES \
GLSL_SOFTWARE_FRAGMENT_SHADER
// same as above but multiplies results with the lighting value from the
// accompanying vertex shader (stored in gl_Color) if model lighting is enabled
#define GLSL_MODEL_FRAGMENT_SHADER \
GLSL_WALL_FUDGES \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"uniform sampler2D tex;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler2D lighttable_tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform float lighting;\n" \
GLSL_DOOM_COLORMAP \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"#ifdef SRB2_MODEL_LIGHTING\n" \
"texel *= gl_Color;\n" \
"#endif\n" \
GLSL_PALETTE_RENDERING \
"}\n" \
"#else\n" \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"#ifdef SRB2_MODEL_LIGHTING\n" \
"final_color *= gl_Color;\n" \
"#endif\n" \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\n" \
"#endif\0"
//
// Water surface shader
//
// Mostly guesstimated, rather than the rest being built off Software science.
// Still needs to distort things underneath/around the water...
//
#define GLSL_WATER_TEXEL \
"float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
"float a = -pi * (water_z * freq) + (leveltime * speed);\n" \
"float sdistort = sin(a) * amp;\n" \
"float cdistort = cos(a) * amp;\n" \
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n"
#define GLSL_WATER_FRAGMENT_SHADER \
GLSL_FLOOR_FUDGES \
"const float freq = 0.025;\n" \
"const float amp = 0.025;\n" \
"const float speed = 2.0;\n" \
"const float pi = 3.14159;\n" \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"uniform sampler2D tex;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler2D lighttable_tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform float lighting;\n" \
"uniform float leveltime;\n" \
GLSL_DOOM_COLORMAP \
"void main(void) {\n" \
GLSL_WATER_TEXEL \
GLSL_PALETTE_RENDERING \
"}\n" \
"#else\n" \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
"uniform float leveltime;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
GLSL_WATER_TEXEL \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\n" \
"#endif\0"
//
// Fog block shader
//
// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha
//
// The floor fudges are used, but should the wall fudges be used instead? or something inbetween?
// or separate values for floors and walls? (need to change more than this shader for that)
#define GLSL_FOG_FRAGMENT_SHADER \
GLSL_FLOOR_FUDGES \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 base_color = gl_Color;\n" \
"vec4 final_color = base_color;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"gl_FragColor = final_color;\n" \
"}\0"
//
// Sky fragment shader
// Modulates poly_color with gl_Color
//
#define GLSL_SKY_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"void main(void) {\n" \
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
"}\0"
// Shader for the palette rendering postprocess step
#define GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler1D palette_tex;\n" \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
"float palette_coord = (tex_pal_idx + 0.5) / 256.0;\n" \
"vec4 final_color = texture1D(palette_tex, palette_coord);\n" \
"gl_FragColor = final_color;\n" \
"}\0"
// Applies a palettized colormap fade to tex
#define GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform float lighting;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
"uniform sampler2D lighttable_tex;\n" \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \
"gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \
"}\0"
// For wipes that use additive and subtractive blending.
// alpha_factor = 31 * 8 / 10 = 24.8
// Calculated based on the use of the "fade" variable from the GETCOLOR macro
// in r_data.c:R_CreateFadeColormaps.
// However this value created some ugliness in fades to white (special stage entry)
// while palette rendering is enabled, so I raised the value just a bit.
#define GLSL_UI_TINTED_WIPE_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"const float alpha_factor = 24.875;\n" \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"vec4 final_color = poly_color;\n" \
"float alpha = texel.a;\n" \
"if (final_color.a >= 0.5)\n" \
"alpha = 1.0 - alpha;\n" \
"alpha *= alpha_factor;\n" \
"final_color *= alpha;\n" \
"final_color.a = 1.0;\n" \
"gl_FragColor = final_color;\n" \
"}\0"
//
// Generic vertex shader
//
#define GLSL_FALLBACK_VERTEX_SHADER \
"void main()\n" \
"{\n" \
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
"gl_FrontColor = gl_Color;\n" \
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
"}\0"
//
// Generic fragment shader
//
#define GLSL_FALLBACK_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"void main(void) {\n" \
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
"}\0"
//
// Software fragment shader
//
#define GLSL_SOFTWARE_FADE_EQUATION \
"float darkness = R_DoomLightingEquation(lighting);\n" \
"if (fade_start != 0.0 || fade_end != 31.0) {\n" \
"float fs = fade_start / 31.0;\n" \
"float fe = fade_end / 31.0;\n" \
"float fd = fe - fs;\n" \
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
"}\n" \
"final_color = mix(final_color, fade_color, darkness);\n"
// same as above but multiplies results with the lighting value from the
// accompanying vertex shader (stored in gl_Color)
#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"final_color *= gl_Color;\n" \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\0"
//
// Sky fragment shader
// Modulates poly_color with gl_Color
//
#define GLSL_SKY_FRAGMENT_SHADER \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"void main(void) {\n" \
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
"}\0"
#endif

File diff suppressed because it is too large Load diff

View file

@ -46,6 +46,7 @@
#define _CREATE_DLL_ // necessary for Unix AND Windows
#include "../../doomdef.h"
#include "../hw_drv.h"
#include "../../z_zone.h"
// ==========================================================================
// DEFINITIONS

View file

@ -620,7 +620,7 @@ static void Command_CSay_f(void)
DoSayCommand(0, 1, HU_CSAY);
}
static tic_t spam_tokens[MAXPLAYERS];
static tic_t spam_tokens[MAXPLAYERS] = { 1 }; // fill the buffer with 1 so the motd can be sent.
static tic_t spam_tics[MAXPLAYERS];
/** Receives a message, processing an ::XD_SAY command.

View file

@ -21,6 +21,7 @@
#include "i_system.h" // I_GetPreciseTime
#include "m_misc.h"
#include "st_stuff.h" // st_palette
#include "doomstat.h" // singletics
#ifdef HWRENDER
#include "hardware/hw_main.h"
@ -604,7 +605,7 @@ static void GIF_framewrite(void)
UINT16 delay = 0;
INT32 startline;
if (gif_dynamicdelay ==(UINT8) 2)
if (gif_dynamicdelay ==(UINT8) 2 && !singletics)
{
// golden's attempt at creating a "dynamic delay"
UINT16 mingifdelay = 10; // minimum gif delay in milliseconds (keep at 10 because gifs can't get more precise).
@ -617,7 +618,7 @@ static void GIF_framewrite(void)
gif_delayus -= frames*(mingifdelay*1000); // remove frames by the amount of milliseconds they take. don't reset to 0, the microseconds help consistency.
}
}
else if (gif_dynamicdelay ==(UINT8) 1)
else if (gif_dynamicdelay ==(UINT8) 1 && !singletics)
{
float delayf = ceil(100.0f/NEWTICRATE);

View file

@ -1098,15 +1098,23 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
fixed_t fheight = P_GetSectorFloorZAt(sec, mt->x << FRACBITS, mt->y << FRACBITS);
mt->z = (UINT16)((player->mo->z - fheight)>>FRACBITS);
}
mt->angle = (INT16)(FixedInt(AngleFixed(player->mo->angle)));
mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value;
mt->options = (UINT16)cv_opflags.value;
mt->scale = player->mo->scale;
mt->spritexscale = player->mo->spritexscale;
mt->spriteyscale = player->mo->spriteyscale;
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->pitch = mt->roll = 0;
// Ignore offsets
if (mt->type == MT_EMBLEM)
mt->args[1] = 1;
else
mt->args[0] = 1;
return mt;
}

View file

@ -1406,18 +1406,19 @@ static menuitem_t OP_OpenGLOptionsMenu[] =
{IT_HEADER, NULL, "General", NULL, 51},
{IT_STRING|IT_CVAR, NULL, "Shaders", &cv_glshaders, 63},
{IT_STRING|IT_CVAR, NULL, "Lack of perspective", &cv_glshearing, 73},
{IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 83},
{IT_STRING|IT_CVAR, NULL, "Palette rendering", &cv_glpaletterendering, 73},
{IT_STRING|IT_CVAR, NULL, "Lack of perspective", &cv_glshearing, 83},
{IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 93},
{IT_HEADER, NULL, "Miscellaneous", NULL, 102},
{IT_STRING|IT_CVAR, NULL, "Bit depth", &cv_scr_depth, 114},
{IT_STRING|IT_CVAR, NULL, "Texture filter", &cv_glfiltermode, 124},
{IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_glanisotropicmode, 134},
{IT_HEADER, NULL, "Miscellaneous", NULL, 112},
{IT_STRING|IT_CVAR, NULL, "Bit depth", &cv_scr_depth, 124},
{IT_STRING|IT_CVAR, NULL, "Texture filter", &cv_glfiltermode, 134},
{IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_glanisotropicmode, 144},
#ifdef ALAM_LIGHTING
{IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 144},
{IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 154},
#endif
#if defined (_WINDOWS) && (!(defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL)))
{IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 154},
{IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 164},
#endif
};

View file

@ -1254,7 +1254,7 @@ void M_SaveFrame(void)
// paranoia: should be unnecessary without singletics
static tic_t oldtic = 0;
if (oldtic == I_GetTime())
if (oldtic == I_GetTime() && !singletics)
return;
else
oldtic = I_GetTime();
@ -1978,9 +1978,9 @@ void M_UnGetToken(void)
static tokenizer_t *globalTokenizer = NULL;
void M_TokenizerOpen(const char *inputString)
void M_TokenizerOpen(const char *inputString, size_t len)
{
globalTokenizer = Tokenizer_Open(inputString, 2);
globalTokenizer = Tokenizer_Open(inputString, len, 2);
}
void M_TokenizerClose(void)

View file

@ -12,11 +12,18 @@
#include "m_tokenizer.h"
#include "z_zone.h"
tokenizer_t *Tokenizer_Open(const char *inputString, unsigned numTokens)
tokenizer_t *Tokenizer_Open(const char *inputString, size_t len, unsigned numTokens)
{
tokenizer_t *tokenizer = Z_Malloc(sizeof(tokenizer_t), PU_STATIC, NULL);
const size_t lenpan = 2;
tokenizer->input = inputString;
tokenizer->zdup = malloc(len+lenpan);
for (size_t i = 0; i < lenpan; i++)
{
tokenizer->zdup[len+i] = 0x00;
}
tokenizer->input = M_Memcpy(tokenizer->zdup, inputString, len);
tokenizer->startPos = 0;
tokenizer->endPos = 0;
tokenizer->inputLength = 0;
@ -51,6 +58,7 @@ void Tokenizer_Close(tokenizer_t *tokenizer)
Z_Free(tokenizer->token[i]);
Z_Free(tokenizer->capacity);
Z_Free(tokenizer->token);
free(tokenizer->zdup);
Z_Free(tokenizer);
}

View file

@ -16,6 +16,7 @@
typedef struct Tokenizer
{
char *zdup;
const char *input;
unsigned numTokens;
UINT32 *capacity;
@ -29,7 +30,7 @@ typedef struct Tokenizer
const char *(*get)(struct Tokenizer*, UINT32);
} tokenizer_t;
tokenizer_t *Tokenizer_Open(const char *inputString, unsigned numTokens);
tokenizer_t *Tokenizer_Open(const char *inputString, size_t len, unsigned numTokens);
void Tokenizer_Close(tokenizer_t *tokenizer);
const char *Tokenizer_Read(tokenizer_t *tokenizer, UINT32 i);

View file

@ -394,7 +394,7 @@ consvar_t cv_ps_descriptor = CVAR_INIT ("ps_descriptor", "Average", 0, ps_descri
consvar_t cv_freedemocamera = CVAR_INIT("freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL);
// NOTE: this should be in hw_main.c, but we can't put it there as it breaks dedicated build
consvar_t cv_glallowshaders = CVAR_INIT ("gr_allowclientshaders", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_glallowshaders = CVAR_INIT ("gr_allowcustomshaders", "On", CV_NETVAR, CV_OnOff, NULL);
char timedemo_name[256];
boolean timedemo_csv;
@ -893,6 +893,9 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_renderhitboxinterpolation);
CV_RegisterVar(&cv_renderhitboxgldepth);
CV_RegisterVar(&cv_renderhitbox);
CV_RegisterVar(&cv_renderwalls);
CV_RegisterVar(&cv_renderfloors);
CV_RegisterVar(&cv_renderthings);
CV_RegisterVar(&cv_renderer);
CV_RegisterVar(&cv_scr_depth);
CV_RegisterVar(&cv_scr_width);
@ -4663,15 +4666,28 @@ static void Command_Cheats_f(void)
CV_ResetCheatNetVars();
return;
}
else if (COM_CheckParm("on"))
{
if (!(server || (IsPlayerAdmin(consoleplayer))))
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
else
G_SetUsedCheats(false);
return;
}
if (usedCheats)
CONS_Printf(M_GetText("Cheats are enabled, the game cannot be saved.\n"));
else
CONS_Printf(M_GetText("Cheats are disabled, the game can be saved.\n"));
if (CV_CheatsEnabled())
{
CONS_Printf(M_GetText("At least one CHEAT-marked variable has been changed -- Cheats are enabled.\n"));
CONS_Printf(M_GetText("At least one CHEAT-marked variable has been changed.\n"));
if (server || (IsPlayerAdmin(consoleplayer)))
CONS_Printf(M_GetText("Type CHEATS OFF to reset all cheat variables to default.\n"));
}
else
CONS_Printf(M_GetText("No CHEAT-marked variables are changed -- Cheats are disabled.\n"));
CONS_Printf(M_GetText("No CHEAT-marked variables are changed.\n"));
}
#ifdef _DEBUG

View file

@ -1640,7 +1640,7 @@ boolean CURLPrepareFile(const char* url, int dfilenum)
#endif
// Set user agent, as some servers won't accept invalid user agents.
curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("Sonic Robo Blast 2/v%d.%d", VERSION, SUBVERSION));
curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("Sonic Robo Blast 2/%s", VERSIONSTRING));
// Authenticate if the user so wishes
login = CURLGetLogin(url, NULL);

View file

@ -265,7 +265,7 @@ static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len
#ifdef HAVE_MINIUPNPC // based on old XChat patch
static void I_ShutdownUPnP(void);
static void I_InitUPnP(void);
I_mutex upnp_mutex;
static I_mutex upnp_mutex;
static struct UPNPUrls urls;
static struct IGDdatas data;
static char lanaddr[64];
@ -300,7 +300,11 @@ init_upnpc_once(struct upnpdata *upnpuserdata)
int upnp_error = -2;
int scope_id = 0;
int status_code = 0;
CONS_Printf(M_GetText("Looking for UPnP Internet Gateway Device\n"));
memset(&urls, 0, sizeof(struct UPNPUrls));
memset(&data, 0, sizeof(struct IGDdatas));
I_OutputMsg(M_GetText("Looking for UPnP Internet Gateway Device\n"));
devlist = upnpDiscoverDevices(deviceTypes, 500, NULL, NULL, 0, false, 2, &upnp_error, 0);
if (devlist)
{
@ -316,39 +320,37 @@ init_upnpc_once(struct upnpdata *upnpuserdata)
if (!dev)
dev = devlist; /* defaulting to first device */
CONS_Printf(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"),
I_OutputMsg(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"),
dev->descURL, dev->st);
UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
CONS_Printf(M_GetText("Local LAN IP address: %s\n"), lanaddr);
I_OutputMsg(M_GetText("Local LAN IP address: %s\n"), lanaddr);
descXML = miniwget(dev->descURL, &descXMLsize, scope_id, &status_code);
if (descXML)
{
parserootdesc(descXML, descXMLsize, &data);
free(descXML);
descXML = NULL;
memset(&urls, 0, sizeof(struct UPNPUrls));
memset(&data, 0, sizeof(struct IGDdatas));
GetUPNPUrls(&urls, &data, dev->descURL, status_code);
I_AddExitFunc(I_ShutdownUPnP);
}
freeUPNPDevlist(devlist);
I_unlock_mutex(upnp_mutex);
}
else if (upnp_error == UPNPDISCOVER_SOCKET_ERROR)
{
CONS_Printf(M_GetText("No UPnP devices discovered\n"));
I_OutputMsg(M_GetText("No UPnP devices discovered\n"));
}
I_unlock_mutex(upnp_mutex);
upnpuserdata->upnpc_started =1;
}
static inline void I_UPnP_add(const char * addr, const char *port, const char * servicetype)
{
if (!urls.controlURL || urls.controlURL[0] == '\0')
return;
I_lock_mutex(&upnp_mutex);
if (addr == NULL)
addr = lanaddr;
if (!urls.controlURL || urls.controlURL[0] == '\0')
return;
UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port, port, addr, "SRB2", servicetype, NULL, NULL);
I_unlock_mutex(upnp_mutex);
@ -356,9 +358,9 @@ static inline void I_UPnP_add(const char * addr, const char *port, const char *
static inline void I_UPnP_rem(const char *port, const char * servicetype)
{
I_lock_mutex(&upnp_mutex);
if (!urls.controlURL || urls.controlURL[0] == '\0')
return;
I_lock_mutex(&upnp_mutex);
UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype,
port, servicetype, NULL);
I_unlock_mutex(upnp_mutex);
@ -1132,10 +1134,10 @@ boolean I_InitTcpDriver(void)
{
I_AddExitFunc(I_ShutdownTcpDriver);
#ifdef HAVE_MINIUPNPC
if (M_CheckParm("-noUPnP"))
UPNP_support = false;
else
if (M_CheckParm("-useUPnP"))
I_InitUPnP();
else
UPNP_support = false;
#endif
}
return init_tcp_driver;

View file

@ -541,7 +541,7 @@ boolean P_Move(mobj_t *actor, fixed_t speed)
if (!P_TryMove(actor, tryx, tryy, false))
{
if (actor->flags & MF_FLOAT && floatok)
if (!P_MobjWasRemoved(actor) && actor->flags & MF_FLOAT && floatok)
{
// must adjust height
if (actor->z < tmfloorz)
@ -585,6 +585,7 @@ void P_NewChaseDir(mobj_t *actor)
dirtype_t d[3];
dirtype_t tdir = DI_NODIR, olddir, turnaround;
I_Assert(!P_MobjWasRemoved(actor));
I_Assert(actor->target != NULL);
I_Assert(!P_MobjWasRemoved(actor->target));
@ -623,7 +624,7 @@ void P_NewChaseDir(mobj_t *actor)
dirtype_t newdir = diags[((deltay < 0)<<1) + (deltax > 0)];
actor->movedir = newdir;
if ((newdir != turnaround) && P_TryWalk(actor))
if ((newdir != turnaround) && (P_TryWalk(actor) || P_MobjWasRemoved(actor)))
return;
}
@ -644,7 +645,7 @@ void P_NewChaseDir(mobj_t *actor)
{
actor->movedir = d[1];
if (P_TryWalk(actor))
if (P_TryWalk(actor) || P_MobjWasRemoved(actor))
return; // either moved forward or attacked
}
@ -652,7 +653,7 @@ void P_NewChaseDir(mobj_t *actor)
{
actor->movedir = d[2];
if (P_TryWalk(actor))
if (P_TryWalk(actor) || P_MobjWasRemoved(actor))
return;
}
@ -661,7 +662,7 @@ void P_NewChaseDir(mobj_t *actor)
{
actor->movedir =olddir;
if (P_TryWalk(actor))
if (P_TryWalk(actor) || P_MobjWasRemoved(actor))
return;
}
@ -674,7 +675,7 @@ void P_NewChaseDir(mobj_t *actor)
{
actor->movedir = tdir;
if (P_TryWalk(actor))
if (P_TryWalk(actor) || P_MobjWasRemoved(actor))
return;
}
}
@ -687,7 +688,7 @@ void P_NewChaseDir(mobj_t *actor)
{
actor->movedir = tdir;
if (P_TryWalk(actor))
if (P_TryWalk(actor) || P_MobjWasRemoved(actor))
return;
}
}
@ -697,7 +698,7 @@ void P_NewChaseDir(mobj_t *actor)
{
actor->movedir = turnaround;
if (P_TryWalk(actor))
if (P_TryWalk(actor) || P_MobjWasRemoved(actor))
return;
}
@ -1100,7 +1101,7 @@ nomissile:
return; // got a new target
// chase towards player
if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed))
if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor)))
P_NewChaseDir(actor);
}
@ -1188,7 +1189,7 @@ nomissile:
return; // got a new target
// chase towards player
if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed))
if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor)))
P_NewChaseDir(actor);
}
@ -1266,7 +1267,8 @@ void A_FaceStabRev(mobj_t *actor)
else
{
P_TryMove(actor, actor->x - P_ReturnThrustX(actor, actor->angle, 2<<FRACBITS), actor->y - P_ReturnThrustY(actor, actor->angle, 2<<FRACBITS), false);
P_FaceStabFlume(actor);
if (!P_MobjWasRemoved(actor))
P_FaceStabFlume(actor);
}
}
}
@ -1332,8 +1334,9 @@ void A_FaceStabHurl(mobj_t *actor)
while (step > 0)
{
if (!hwork->hnext)
if (P_MobjWasRemoved(hwork->hnext))
P_SetTarget(&hwork->hnext, P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_FACESTABBERSPEAR));
if (!P_MobjWasRemoved(hwork->hnext))
{
hwork = hwork->hnext;
@ -1341,6 +1344,20 @@ void A_FaceStabHurl(mobj_t *actor)
P_SetScale(hwork, FixedSqrt(step*basesize), true);
hwork->fuse = 2;
P_MoveOrigin(hwork, actor->x + xo*(15-step), actor->y + yo*(15-step), actor->z + (actor->height - hwork->height)/2 + (P_MobjFlip(actor)*(8<<FRACBITS)));
if (P_MobjWasRemoved(hwork))
{
// if one of the sections are removed, erase the entire damn thing.
mobj_t *hnext = actor->hnext;
hwork = actor;
do
{
hnext = hwork->hnext;
P_RemoveMobj(hwork);
hwork = hnext;
}
while (!P_MobjWasRemoved(hwork));
return;
}
}
step -= NUMGRADS;
}
@ -1357,11 +1374,14 @@ void A_FaceStabHurl(mobj_t *actor)
#undef NUMGRADS
#undef NUMSTEPS
}
if (P_MobjWasRemoved(actor))
return;
}
}
P_SetMobjState(actor, locvar2);
actor->reactiontime = actor->info->reactiontime;
if (!P_MobjWasRemoved(actor))
actor->reactiontime = actor->info->reactiontime;
}
// Function: A_FaceStabMiss
@ -1391,6 +1411,8 @@ void A_FaceStabMiss(mobj_t *actor)
actor->y + P_ReturnThrustY(actor, actor->angle, actor->extravalue2<<FRACBITS),
false))
{
if (P_MobjWasRemoved(actor))
return;
actor->extravalue2 = 0;
P_SetMobjState(actor, locvar2);
}
@ -1423,6 +1445,8 @@ void A_StatueBurst(mobj_t *actor)
P_SetTarget(&new->target, actor->target);
if (locvar2)
P_SetMobjState(new, (statenum_t)locvar2);
if (P_MobjWasRemoved(new))
return;
S_StartSound(new, new->info->attacksound);
S_StopSound(actor);
S_StartSound(actor, sfx_s3k96);
@ -1518,7 +1542,7 @@ void A_JetJawChomp(mobj_t *actor)
}
// chase towards player
if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed))
if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor)))
P_NewChaseDir(actor);
}
@ -1939,14 +1963,15 @@ void A_SharpChase(mobj_t *actor)
}
// chase towards player
if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed))
if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor)))
P_NewChaseDir(actor);
}
else
{
actor->threshold = actor->info->painchance;
P_SetMobjState(actor, actor->info->missilestate);
S_StartSound(actor, actor->info->attacksound);
if (!P_MobjWasRemoved(actor))
S_StartSound(actor, actor->info->attacksound);
}
}
@ -2032,6 +2057,8 @@ void A_CrushstaceanWalk(mobj_t *actor)
false)
|| (actor->reactiontime-- <= 0))
{
if (P_MobjWasRemoved(actor))
return;
actor->flags2 ^= MF2_AMBUSH;
P_SetTarget(&actor->target, NULL);
P_SetMobjState(actor, locvar2);
@ -2213,6 +2240,8 @@ void A_CrushclawLaunch(mobj_t *actor)
true)
&& !locvar1)
{
if (P_MobjWasRemoved(actor))
return;
actor->extravalue1 = 0;
actor->extravalue2 = FixedHypot(actor->x - actor->target->x, actor->y - actor->target->y)>>FRACBITS;
P_SetMobjState(actor, locvar2);
@ -2221,6 +2250,8 @@ void A_CrushclawLaunch(mobj_t *actor)
}
else
{
if (P_MobjWasRemoved(actor))
return;
actor->z = actor->target->z;
if ((!locvar1 && (actor->extravalue2 > 256)) || (locvar1 && (actor->extravalue2 < 16)))
{
@ -2646,7 +2677,7 @@ nomissile:
return; // got a new target
// chase towards player
if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed))
if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor)))
P_NewChaseDir(actor);
}
@ -5771,7 +5802,11 @@ void A_MinusDigging(mobj_t *actor)
if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < actor->radius*2)
{
P_SetMobjState(actor, actor->info->meleestate);
if (P_MobjWasRemoved(actor))
return;
P_TryMove(actor, actor->target->x, actor->target->y, false);
if (P_MobjWasRemoved(actor))
return;
S_StartSound(actor, actor->info->attacksound);
// Spawn growing dirt pile.
@ -5779,7 +5814,9 @@ void A_MinusDigging(mobj_t *actor)
if (P_MobjWasRemoved(par))
return;
P_SetMobjState(par, actor->info->raisestate);
P_SetScale(par, 2*actor->scale, false);
if (P_MobjWasRemoved(par))
return;
P_SetScale(par, actor->scale*2);
par->old_scale = par->scale;
if (actor->eflags & MFE_VERTICALFLIP)
par->eflags |= MFE_VERTICALFLIP;
@ -5793,6 +5830,8 @@ void A_MinusDigging(mobj_t *actor)
// Move
var1 = 3;
A_Chase(actor);
if (P_MobjWasRemoved(actor))
return;
// Carry over shit, maybe
if (P_MobjWasRemoved(actor->tracer) || !actor->tracer->health)
@ -5816,7 +5855,7 @@ void A_MinusDigging(mobj_t *actor)
{
if (P_TryMove(actor->tracer, actor->x, actor->y, false))
actor->tracer->z = mz;
else
else if (!P_MobjWasRemoved(actor))
P_SetTarget(&actor->tracer, NULL);
}
}
@ -7290,7 +7329,7 @@ nomissile:
// chase towards player
if (P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) > actor->radius+actor->target->radius)
{
if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed))
if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor)))
P_NewChaseDir(actor);
}
// too close, don't want to chase.
@ -7647,7 +7686,7 @@ void A_Boss7Chase(mobj_t *actor)
if (leveltime & 1)
{
// chase towards player
if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed))
if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor)))
P_NewChaseDir(actor);
}
}
@ -8105,6 +8144,8 @@ void A_GuardChase(mobj_t *actor)
false)
&& speed > 0) // can't be the same check as previous so that P_TryMove gets to happen.
{
if (P_MobjWasRemoved(actor))
return;
INT32 direction = actor->spawnpoint ? actor->spawnpoint->args[0] : TMGD_BACK;
switch (direction)
@ -8121,6 +8162,8 @@ void A_GuardChase(mobj_t *actor)
break;
}
}
if (P_MobjWasRemoved(actor))
return;
if (actor->extravalue1 < actor->info->speed)
actor->extravalue1++;
@ -8157,7 +8200,11 @@ void A_GuardChase(mobj_t *actor)
// chase towards player
if (--actor->movecount < 0 || !P_Move(actor, (actor->flags2 & MF2_AMBUSH) ? actor->info->speed * 2 : actor->info->speed))
{
if (P_MobjWasRemoved(actor))
return;
P_NewChaseDir(actor);
if (P_MobjWasRemoved(actor))
return;
actor->movecount += 5; // Increase tics before change in direction allowed.
}
}
@ -8628,6 +8675,9 @@ void A_PlaySeeSound(mobj_t *actor)
if (LUA_CallAction(A_PLAYSEESOUND, actor))
return;
if (P_MobjWasRemoved(actor))
return;
if (actor->info->seesound)
S_StartScreamSound(actor, actor->info->seesound);
}
@ -11718,7 +11768,13 @@ void A_BrakChase(mobj_t *actor)
// chase towards player
if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed))
{
if (P_MobjWasRemoved(actor))
return;
P_NewChaseDir(actor);
if (P_MobjWasRemoved(actor))
return;
}
// Optionally play a sound effect
if (locvar2 > 0 && locvar2 < NUMSFX)
@ -13296,6 +13352,8 @@ void A_DoNPCSkid(mobj_t *actor)
if ((FixedHypot(actor->momx, actor->momy) < locvar2)
|| !P_TryMove(actor, actor->x + actor->momx, actor->y + actor->momy, false))
{
if (P_MobjWasRemoved(actor))
return;
actor->momx = actor->momy = 0;
P_SetMobjState(actor, locvar1);
return;
@ -13838,6 +13896,8 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing)
y = dustdevil->y;
}
P_TryMove(thing, x - thing->momx, y - thing->momy, true);
if (P_MobjWasRemoved(thing))
return false;
}
else
{ //Player on the top of the tornado.
@ -14243,6 +14303,8 @@ static void P_SnapperLegPlace(mobj_t *mo)
seg->z = mo->z + ((mo->eflags & MFE_VERTICALFLIP) ? (((mo->height<<1)/3) - seg->height) : mo->height/3);
P_TryMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, true);
if (P_MobjWasRemoved(seg))
return;
seg->angle = a;
// Move as many legs as available.
@ -14264,6 +14326,8 @@ static void P_SnapperLegPlace(mobj_t *mo)
y = s*o2 - c*o1;
seg->z = mo->z + (((mo->eflags & MFE_VERTICALFLIP) ? (mo->height - seg->height) : 0));
P_TryMove(seg, mo->x + x, mo->y + y, true);
if (P_MobjWasRemoved(seg))
return;
P_SetMobjState(seg, seg->info->raisestate);
}
else
@ -14407,6 +14471,8 @@ void A_SnapperThinker(mobj_t *actor)
s = FINESINE(fa);
P_TryMove(actor, actor->x + c*speed, actor->y + s*speed, false);
if (P_MobjWasRemoved(actor))
return;
// The snapper spawns dust if going fast!
if (actor->reactiontime < 4)

View file

@ -1397,11 +1397,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
i = 0;
for (; special->type == MT_HOOP; special = special->hnext)
{
special->fuse = 11;
special->movedir = i;
special->extravalue1 = special->target->extravalue1;
special->extravalue2 = special->target->extravalue2;
special->target->threshold = 4242;
if (!P_MobjWasRemoved(special->target))
{
special->fuse = 11;
special->movedir = i;
special->extravalue1 = special->target->extravalue1;
special->extravalue2 = special->target->extravalue2;
special->target->threshold = 4242;
}
i++;
}
// Make the collision detectors disappear.

View file

@ -2734,7 +2734,7 @@ increment_move
tryy = y;
}
if (!P_CheckPosition(thing, tryx, tryy))
if (!P_CheckPosition(thing, tryx, tryy) || P_MobjWasRemoved(thing))
return false; // solid wall or thing
if (!(thing->flags & MF_NOCLIP))
@ -2958,6 +2958,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
{
fixed_t tryx, tryy;
I_Assert(!P_MobjWasRemoved(thing));
tryx = thing->x;
tryy = thing->y;
@ -2975,7 +2976,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
else
tryy = y;
if (!P_CheckPosition(thing, tryx, tryy))
if (!P_CheckPosition(thing, tryx, tryy) || P_MobjWasRemoved(thing))
return false; // solid wall or thing
if (!(thing->flags & MF_NOCLIP))
@ -3714,6 +3715,12 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
}
}
static inline void P_StairStepSlideMove(mobj_t *mo)
{
if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true) && !P_MobjWasRemoved(mo)) //Allow things to drop off.
P_TryMove(mo, mo->x + mo->momx, mo->y, true);
}
//
// P_SlideMove
// The momx / momy move is bad, so try to slide
@ -3735,6 +3742,8 @@ void P_SlideMove(mobj_t *mo)
memset(&junk, 0x00, sizeof(junk));
I_Assert(!P_MobjWasRemoved(mo));
if (tmhitthing && mo->z + mo->height > tmhitthing->z && mo->z < tmhitthing->z + tmhitthing->height)
{
// Don't mess with your momentum if it's a pushable object. Pushables do their own crazy things already.
@ -3869,7 +3878,10 @@ void P_SlideMove(mobj_t *mo)
retry:
if ((++hitcount == 3) || papercol)
goto stairstep; // don't loop forever
{
P_StairStepSlideMove(mo);
return;
}
// trace along the three leading corners
if (mo->momx > 0)
@ -3921,9 +3933,7 @@ papercollision:
if (bestslidefrac == FRACUNIT+1)
{
// the move must have hit the middle, so stairstep
stairstep:
if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true)) //Allow things to drop off.
P_TryMove(mo, mo->x + mo->momx, mo->y, true);
P_StairStepSlideMove(mo);
return;
}
@ -3935,7 +3945,13 @@ stairstep:
newy = FixedMul(mo->momy, bestslidefrac);
if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true))
goto stairstep;
{
if (!P_MobjWasRemoved(mo))
P_StairStepSlideMove(mo);
return;
}
if (P_MobjWasRemoved(mo))
return;
}
// Now continue along the wall.
@ -3986,11 +4002,13 @@ stairstep:
tmymove = 0;
}
if (!P_TryMove(mo, newx, newy, true)) {
if (success)
if (success || P_MobjWasRemoved(mo))
return; // Good enough!!
else
goto retry;
}
if (P_MobjWasRemoved(mo))
return;
success = true;
} while(tmxmove || tmymove);
}

View file

@ -2118,7 +2118,7 @@ void P_RingXYMovement(mobj_t *mo)
I_Assert(mo != NULL);
I_Assert(!P_MobjWasRemoved(mo));
if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy))
if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy) && !P_MobjWasRemoved(mo))
P_SlideMove(mo);
}
@ -2132,8 +2132,10 @@ void P_SceneryXYMovement(mobj_t *mo)
oldx = mo->x;
oldy = mo->y;
if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy))
if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy) && !P_MobjWasRemoved(mo))
P_SlideMove(mo);
if (P_MobjWasRemoved(mo))
return;
if ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z > mo->floorz) || (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height < mo->ceilingz))
return; // no friction when airborne
@ -2329,12 +2331,15 @@ boolean P_CheckDeathPitCollide(mobj_t *mo)
if (mo->player && mo->player->pflags & PF_GODMODE)
return false;
if (((mo->z <= mo->subsector->sector->floorheight
fixed_t sectorFloor = P_GetSectorFloorZAt(mo->subsector->sector, mo->x, mo->y);
fixed_t sectorCeiling = P_GetSectorCeilingZAt(mo->subsector->sector, mo->x, mo->y);
if (((mo->z <= sectorFloor
&& ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_FLOOR))
|| (mo->z + mo->height >= mo->subsector->sector->ceilingheight
&& ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_CEILING)))
&& (mo->subsector->sector->damagetype == SD_DEATHPITTILT
|| mo->subsector->sector->damagetype == SD_DEATHPITNOTILT))
|| (mo->z + mo->height >= sectorCeiling
&& ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_CEILING)))
&& (mo->subsector->sector->damagetype == SD_DEATHPITTILT
|| mo->subsector->sector->damagetype == SD_DEATHPITNOTILT))
return true;
return false;
@ -3906,6 +3911,8 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
}
else
P_TryMove(mobj, mobj->x, mobj->y, true);
if (P_MobjWasRemoved(mobj))
return;
P_CheckCrumblingPlatforms(mobj);
@ -4700,6 +4707,8 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz)
{
seg->z = bz + (dz*(9-s));
P_TryMove(seg, workx + (dx*s), worky + (dy*s), true);
if (P_MobjWasRemoved(seg))
return;
}
angle += ANGLE_MAX/3;
}
@ -4937,6 +4946,8 @@ static void P_Boss4Thinker(mobj_t *mobj)
(mobj->spawnpoint->x<<FRACBITS) - P_ReturnThrustX(mobj, mobj->angle, mobj->movefactor),
(mobj->spawnpoint->y<<FRACBITS) - P_ReturnThrustY(mobj, mobj->angle, mobj->movefactor),
true);
if (P_MobjWasRemoved(mobj))
return;
P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2);
@ -5505,6 +5516,8 @@ static void P_Boss9Thinker(mobj_t *mobj)
{
P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT);
P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true);
if (P_MobjWasRemoved(mobj))
return;
mobj->momz -= gravity;
if (mobj->z < mobj->watertop || mobj->z < (mobj->floorz + 16*FRACUNIT))
{
@ -5848,6 +5861,8 @@ static void P_Boss9Thinker(mobj_t *mobj)
P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT);
if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true))
{ // Hit a wall? Find a direction to bounce
if (P_MobjWasRemoved(mobj))
return;
mobj->threshold--;
if (!mobj->threshold) { // failed bounce!
S_StartSound(mobj, sfx_mspogo);
@ -5888,6 +5903,8 @@ static void P_Boss9Thinker(mobj_t *mobj)
P_InstaThrust(mobj, mobj->angle, -speed);
while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16)
{
if (P_MobjWasRemoved(mobj))
return;
S_StartSound(mobj, sfx_mspogo);
P_BounceMove(mobj);
mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0);
@ -7487,6 +7504,8 @@ static void P_RosySceneryThink(mobj_t *mobj)
fixed_t x = mobj->x, y = mobj->y, z = mobj->z;
angle_t angletoplayer = R_PointToAngle2(x, y, mobj->target->x, mobj->target->y);
boolean allowed = P_TryMove(mobj, mobj->target->x, mobj->target->y, false);
if (P_MobjWasRemoved(mobj))
return;
P_UnsetThingPosition(mobj);
mobj->x = x;
@ -8052,7 +8071,8 @@ static void P_MobjSceneryThink(mobj_t *mobj)
break;
}
P_SceneryThinker(mobj);
if (!P_MobjWasRemoved(mobj))
P_SceneryThinker(mobj);
}
static boolean P_MobjPushableThink(mobj_t *mobj)
@ -10282,6 +10302,8 @@ void P_MobjThinker(mobj_t *mobj)
P_SetTarget(&mobj->hnext, NULL);
if (mobj->hprev && P_MobjWasRemoved(mobj->hprev))
P_SetTarget(&mobj->hprev, NULL);
if (mobj->dontdrawforviewmobj && P_MobjWasRemoved(mobj->dontdrawforviewmobj))
P_SetTarget(&mobj->dontdrawforviewmobj, NULL);
mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG);
@ -10412,6 +10434,8 @@ void P_MobjThinker(mobj_t *mobj)
|| mobj->type == MT_CANNONBALLDECOR
|| mobj->type == MT_FALLINGROCK) {
P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly
if (P_MobjWasRemoved(mobj))
return;
//if (mobj->standingslope) CONS_Printf("slope physics on mobj\n");
P_ButteredSlope(mobj);
}
@ -10513,6 +10537,8 @@ void P_PushableThinker(mobj_t *mobj)
// it has to be pushable RIGHT NOW for this part to happen
if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy))
P_TryMove(mobj, mobj->x, mobj->y, true);
if (P_MobjWasRemoved(mobj))
return;
if (mobj->type == MT_MINECART && mobj->health)
{
@ -10855,9 +10881,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
)))
mobj->flags2 |= MF2_DONTRESPAWN;
if (!(mobj->flags & MF_NOTHINK))
P_AddThinker(THINK_MOBJ, &mobj->thinker);
if (type == MT_PLAYER)
{
// when spawning MT_PLAYER, set mobj->player before calling MobjSpawn hook to prevent P_RemoveMobj from succeeding on player mobj.
@ -10867,6 +10890,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
va_end(args);
}
if (!(mobj->flags & MF_NOTHINK) || (titlemapinaction && mobj->type == MT_ALTVIEWMAN))
P_AddThinker(THINK_MOBJ, &mobj->thinker);
// increment mobj reference, so we don't get a dangling reference in case MobjSpawn calls P_RemoveMobj
mobj->thinker.references++;
@ -14006,7 +14032,8 @@ boolean P_CheckMissileSpawn(mobj_t *th)
if (!P_TryMove(th, th->x, th->y, true))
{
P_ExplodeMissile(th);
if (!P_MobjWasRemoved(th))
P_ExplodeMissile(th);
return false;
}
return true;

View file

@ -585,17 +585,17 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
// Look for a flat
int texturenum = R_CheckFlatNumForName(levelflat->name);
if (texturenum <= 0)
if (texturenum < 0)
{
// If we can't find a flat, try looking for a texture!
texturenum = R_CheckTextureNumForName(levelflat->name);
if (texturenum <= 0)
if (texturenum < 0)
{
// Use "not found" texture
texturenum = R_CheckTextureNumForName("REDWALL");
// Give up?
if (texturenum <= 0)
if (texturenum < 0)
{
levelflat->type = LEVELFLAT_NONE;
texturenum = -1;
@ -1525,6 +1525,12 @@ static boolean TextmapCount(size_t size)
numvertexes = 0;
numsectors = 0;
if(!tkn)
{
CONS_Alert(CONS_ERROR, "No text in lump!\n");
return true;
}
// Look for namespace at the beginning.
if (!fastcmp(tkn, "namespace"))
{
@ -3109,7 +3115,12 @@ static boolean P_LoadMapData(const virtres_t *virt)
if (udmf) // Count how many entries for each type we got in textmap.
{
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
M_TokenizerOpen((char *)textmap->data);
if (textmap->size == 0)
{
CONS_Alert(CONS_ERROR, "Emtpy TEXTMAP Lump!\n");
return false;
}
M_TokenizerOpen((char *)textmap->data, textmap->size);
if (!TextmapCount(textmap->size))
{
M_TokenizerClose();

View file

@ -844,7 +844,7 @@ void P_Ticker(boolean run)
if (quake.time)
--quake.time;
if (metalplayback)
if (!P_MobjWasRemoved(metalplayback))
G_ReadMetalTic(metalplayback);
if (metalrecording)
G_WriteMetalTic(players[consoleplayer].mo);

View file

@ -11084,7 +11084,8 @@ static void P_MinecartThink(player_t *player)
fa = (minecart->angle >> ANGLETOFINESHIFT) & FINEMASK;
if (!P_TryMove(minecart, minecart->x + FINECOSINE(fa), minecart->y + FINESINE(fa), true))
{
P_KillMobj(minecart, NULL, NULL, 0);
if (!P_MobjWasRemoved(minecart))
P_KillMobj(minecart, NULL, NULL, 0);
return;
}
@ -12441,7 +12442,7 @@ void P_PlayerThink(player_t *player)
player->texttimer = 4*TICRATE;
player->textvar = 2; // GET n RINGS!
if (player->capsule && player->capsule->health != player->capsule->spawnpoint->angle)
if (!P_MobjWasRemoved(player->capsule) && player->capsule->health != player->capsule->spawnpoint->angle)
player->textvar++; // GET n MORE RINGS!
}
}

View file

@ -31,6 +31,10 @@
#include "byteptr.h"
#include "dehacked.h"
#ifdef HWRENDER
#include "hardware/hw_glob.h" // HWR_ClearLightTables
#endif
//
// Graphics.
// SRB2 graphics for walls and sprites
@ -426,6 +430,9 @@ void R_ClearColormaps(void)
{
// Purged by PU_LEVEL, just overwrite the pointer
extra_colormaps = R_CreateDefaultColormap(true);
#ifdef HWRENDER
HWR_ClearLightTables();
#endif
}
//

View file

@ -25,6 +25,10 @@
#include "screen.h" // MAXVIDWIDTH, MAXVIDHEIGHT
#ifdef HWRENDER
#include "m_aatree.h"
#endif
#include "taglist.h"
//
@ -69,6 +73,11 @@ typedef struct extracolormap_s
lighttable_t *colormap;
#ifdef HWRENDER
// The id of the hardware lighttable. Zero means it does not exist yet.
UINT32 gl_lighttable_id;
#endif
#ifdef EXTRACOLORMAPLUMPS
lumpnum_t lump; // for colormap lump matching, init to LUMPERROR
char lumpname[9]; // for netsyncing
@ -897,6 +906,26 @@ typedef struct
// the [0] is &columnofs[width]
} ATTRPACK softwarepatch_t;
#ifdef _MSC_VER
#pragma warning(disable : 4200)
#endif
// a pic is an unmasked block of pixels, stored in horizontal way
typedef struct
{
INT16 width;
UINT8 zero; // set to 0 allow autodetection of pic_t
// mode instead of patch or raw
UINT8 mode; // see pic_mode_t above
INT16 height;
INT16 reserved1; // set to 0
UINT8 data[0];
} ATTRPACK pic_t;
#ifdef _MSC_VER
#pragma warning(default : 4200)
#endif
#if defined(_MSC_VER)
#pragma pack()
#endif

View file

@ -1363,7 +1363,7 @@ void R_SkyboxFrame(player_t *player)
newview->z += campos.z * -mh->skybox_scalez;
}
if (r_viewmobj->subsector)
if (!P_MobjWasRemoved(r_viewmobj) && r_viewmobj->subsector)
newview->sector = r_viewmobj->subsector->sector;
else
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;

View file

@ -881,6 +881,9 @@ void R_DrawSinglePlane(visplane_t *pl)
if (!(pl->minx <= pl->maxx))
return;
if (!cv_renderfloors.value)
return;
// sky flat
if (pl->picnum == skyflatnum)
{

View file

@ -117,6 +117,9 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
INT32 range;
unsigned lengthcol;
if (!cv_renderwalls.value)
return;
// Calculate light table.
// Use different light tables
// for horizontal / vertical / diagonal. Diagonal?
@ -441,7 +444,7 @@ static void R_DrawRepeatMaskedColumn(column_t *col, unsigned lengthcol)
{
while (sprtopscreen < sprbotscreen) {
R_DrawMaskedColumn(col, lengthcol);
if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
sprtopscreen = INT32_MAX;
else
sprtopscreen += dc_texheight*spryscale;
@ -505,6 +508,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
void (*colfunc_2s) (column_t *, unsigned);
if (!cv_renderwalls.value)
return;
// Calculate light table.
// Use different light tables
// for horizontal / vertical / diagonal. Diagonal?
@ -1247,29 +1253,32 @@ static void R_RenderSegLoop (void)
// single sided line
if (yl <= yh && yh >= 0 && yl < viewheight)
{
fixed_t offset = texturecolumn + rw_offsetx;
if (cv_renderwalls.value)
{
fixed_t offset = texturecolumn + rw_offsetx;
dc_yl = yl;
dc_yh = yh;
dc_texturemid = rw_midtexturemid;
dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_midtexturescaley);
dc_source = R_GetColumn(midtexture, offset >> FRACBITS)->pixels;
dc_texheight = textureheight[midtexture]>>FRACBITS;
dc_yl = yl;
dc_yh = yh;
dc_texturemid = rw_midtexturemid;
dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_midtexturescaley);
dc_source = R_GetColumn(midtexture, offset >> FRACBITS)->pixels;
dc_texheight = textureheight[midtexture]>>FRACBITS;
//profile stuff ---------------------------------------------------------
//profile stuff ---------------------------------------------------------
#ifdef TIMING
ProfZeroTimer();
ProfZeroTimer();
#endif
colfunc();
colfunc();
#ifdef TIMING
RDMSR(0x10,&mycount);
mytotal += mycount; //64bit add
RDMSR(0x10,&mycount);
mytotal += mycount; //64bit add
if (nombre--==0)
I_Error("R_DrawColumn CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1),
(INT32)mytotal);
if (nombre--==0)
I_Error("R_DrawColumn CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1),
(INT32)mytotal);
#endif
//profile stuff ---------------------------------------------------------
//profile stuff ---------------------------------------------------------
}
// dont draw anything more for this column, since
// a midtexture blocks the view
@ -1313,18 +1322,21 @@ static void R_RenderSegLoop (void)
}
else if (mid >= 0) // safe to draw top texture
{
fixed_t offset = rw_offset_top;
if (rw_toptexturescalex < 0)
offset = -offset;
offset = toptexturecolumn + offset;
if (cv_renderwalls.value)
{
fixed_t offset = rw_offset_top;
if (rw_toptexturescalex < 0)
offset = -offset;
offset = toptexturecolumn + offset;
dc_yl = yl;
dc_yh = mid;
dc_texturemid = rw_toptexturemid;
dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_toptexturescaley);
dc_source = R_GetColumn(toptexture, offset >> FRACBITS)->pixels;
dc_texheight = textureheight[toptexture]>>FRACBITS;
colfunc();
dc_yl = yl;
dc_yh = mid;
dc_texturemid = rw_toptexturemid;
dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_toptexturescaley);
dc_source = R_GetColumn(toptexture, offset >> FRACBITS)->pixels;
dc_texheight = textureheight[toptexture]>>FRACBITS;
colfunc();
}
ceilingclip[rw_x] = (INT16)mid;
}
else if (!rw_ceilingmarked) // entirely off top of screen
@ -1361,18 +1373,21 @@ static void R_RenderSegLoop (void)
}
else if (mid < viewheight) // safe to draw bottom texture
{
fixed_t offset = rw_offset_bottom;
if (rw_bottomtexturescalex < 0)
offset = -offset;
offset = bottomtexturecolumn + offset;
if (cv_renderwalls.value)
{
fixed_t offset = rw_offset_bottom;
if (rw_bottomtexturescalex < 0)
offset = -offset;
offset = bottomtexturecolumn + offset;
dc_yl = mid;
dc_yh = yh;
dc_texturemid = rw_bottomtexturemid;
dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_bottomtexturescaley);
dc_source = R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels;
dc_texheight = textureheight[bottomtexture]>>FRACBITS;
colfunc();
dc_yl = mid;
dc_yh = yh;
dc_texturemid = rw_bottomtexturemid;
dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_bottomtexturescaley);
dc_source = R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels;
dc_texheight = textureheight[bottomtexture]>>FRACBITS;
colfunc();
}
floorclip[rw_x] = (INT16)mid;
}
else if (!rw_floormarked) // entirely off bottom of screen

View file

@ -193,6 +193,8 @@ static void R_DrawBlendColumnInCache(column_t *column, UINT8 *cache, texpatch_t
{
for (; dest < cache + position + count; source++, dest++, is_opaque++)
{
if (originPatch->alpha <= ASTTextureBlendingThreshold[1] && !(*is_opaque))
continue;
*dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha);
*is_opaque = true;
}
@ -237,6 +239,8 @@ static void R_DrawBlendFlippedColumnInCache(column_t *column, UINT8 *cache, texp
{
for (; dest < cache + position + count; --source, dest++, is_opaque++)
{
if (originPatch->alpha <= ASTTextureBlendingThreshold[1] && !(*is_opaque))
continue;
*dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha);
*is_opaque = true;
}

View file

@ -1528,6 +1528,9 @@ static void R_ProjectSprite(mobj_t *thing)
// uncapped/interpolation
interpmobjstate_t interp = {0};
if (!cv_renderthings.value)
return;
// do interpolation
if (R_UsingFrameInterpolation() && !paused)
{

View file

@ -784,9 +784,9 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseString(tokenizer_t *sc)
return NULL;
}
static struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char *translation)
static struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char *translation, size_t len)
{
tokenizer_t *sc = Tokenizer_Open(translation, 1);
tokenizer_t *sc = Tokenizer_Open(translation, len, 1);
struct PaletteRemapParseResult *result = PaletteRemap_ParseString(sc);
Tokenizer_Close(sc);
return result;
@ -918,7 +918,7 @@ void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
text[lumpLength] = '\0';
Z_Free(lumpData);
sc = Tokenizer_Open(text, 1);
sc = Tokenizer_Open(text, lumpLength, 1);
tkn = sc->get(sc, 0);
struct NewTranslation *list = NULL;
@ -963,7 +963,7 @@ void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
// Parse all of the translations
do {
struct PaletteRemapParseResult *parse_result = PaletteRemap_ParseTranslation(tkn);
struct PaletteRemapParseResult *parse_result = PaletteRemap_ParseTranslation(tkn, strlen(tkn));
if (parse_result->error)
{
PrintError(name, "%s", parse_result->error);

View file

@ -71,6 +71,9 @@ consvar_t cv_scr_height_w = CVAR_INIT ("scr_height_w", "400", CV_SAVE, CV_Unsign
consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL);
consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL);
consvar_t cv_renderwalls = CVAR_INIT ("renderwalls", "On", CV_NOTINNET|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_renderfloors = CVAR_INIT ("renderfloors", "On", CV_NOTINNET|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_renderthings = CVAR_INIT ("renderthings", "On", CV_NOTINNET|CV_CHEAT, CV_OnOff, NULL);
CV_PossibleValue_t cv_renderer_t[] = {
{1, "Software"},

View file

@ -187,6 +187,7 @@ extern INT32 scr_bpp;
extern UINT8 *scr_borderpatch; // patch used to fill the view borders
extern consvar_t cv_scr_width, cv_scr_height, cv_scr_width_w, cv_scr_height_w, cv_scr_depth, cv_fullscreen;
extern consvar_t cv_renderwalls, cv_renderfloors, cv_renderthings;
extern consvar_t cv_renderview, cv_renderer;
extern consvar_t cv_renderhitbox, cv_renderhitboxinterpolation, cv_renderhitboxgldepth;
// wait for page flipping to end or not

View file

@ -495,6 +495,7 @@
<ClCompile Include="..\hardware\hw_md2load.c" />
<ClCompile Include="..\hardware\hw_md3load.c" />
<ClCompile Include="..\hardware\hw_model.c" />
<ClCompile Include="..\hardware\hw_shaders.c" />
<ClCompile Include="..\hardware\r_opengl\r_opengl.c" />
<ClCompile Include="..\lua_colorlib.c" />
<ClCompile Include="..\r_bbox.c" />

View file

@ -751,6 +751,12 @@
<ClCompile Include="..\hardware\hw_model.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\hw_shaders.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\hardware\u_list.c">
<Filter>Hw_Hardware</Filter>
</ClCompile>
<ClCompile Include="..\filesrch.c">
<Filter>I_Interface</Filter>
</ClCompile>

View file

@ -74,7 +74,7 @@ void *hwSym(const char *funcName,void *handle)
{
void *funcPointer = NULL;
#ifdef HWRENDER
if (0 == strcmp("SetPalette", funcName))
if (0 == strcmp("SetTexturePalette", funcName))
funcPointer = &OglSdlSetPalette;
GETFUNC(Init);
@ -87,7 +87,7 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(SetTexture);
GETFUNC(UpdateTexture);
GETFUNC(DeleteTexture);
GETFUNC(ReadRect);
GETFUNC(ReadScreenTexture);
GETFUNC(GClipRect);
GETFUNC(ClearMipMapCache);
GETFUNC(SetSpecialState);
@ -97,21 +97,23 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(SetTransform);
GETFUNC(PostImgRedraw);
GETFUNC(FlushScreenTextures);
GETFUNC(StartScreenWipe);
GETFUNC(EndScreenWipe);
GETFUNC(DoScreenWipe);
GETFUNC(DrawIntermissionBG);
GETFUNC(DrawScreenTexture);
GETFUNC(MakeScreenTexture);
GETFUNC(MakeScreenFinalTexture);
GETFUNC(DrawScreenFinalTexture);
GETFUNC(CompileShaders);
GETFUNC(CleanShaders);
GETFUNC(InitShaders);
GETFUNC(LoadShader);
GETFUNC(CompileShader);
GETFUNC(SetShader);
GETFUNC(UnSetShader);
GETFUNC(SetShaderInfo);
GETFUNC(LoadCustomShader);
GETFUNC(SetPaletteLookup);
GETFUNC(CreateLightTable);
GETFUNC(ClearLightTables);
GETFUNC(SetScreenPalette);
#else //HWRENDER
if (0 == strcmp("FinishUpdate", funcName))

View file

@ -109,6 +109,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#endif
#if defined (__unix__) || (defined (UNIXCOMMON) && !defined (__APPLE__))
#include <poll.h>
#include <errno.h>
#include <sys/wait.h>
#define NEWSIGNALHANDLER
@ -616,50 +617,60 @@ void I_GetConsoleEvents(void)
// we use this when sending back commands
event_t ev = {0};
char key = 0;
ssize_t d;
struct pollfd pfd =
{
.fd = STDIN_FILENO,
.events = POLLIN,
.revents = 0,
};
if (!consolevent)
return;
ev.type = ev_console;
ev.key = 0;
if (read(STDIN_FILENO, &key, 1) == -1 || !key)
return;
for (;;)
{
if (poll(&pfd, 1, 0) < 1 || !(pfd.revents & POLLIN))
return;
// we have something
// backspace?
// NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere
if ((key == tty_erase) || (key == 127) || (key == 8))
{
if (tty_con.cursor > 0)
ev.type = ev_console;
ev.key = 0;
if (read(STDIN_FILENO, &key, 1) == -1 || !key)
return;
// we have something
// backspace?
// NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere
if ((key == tty_erase) || (key == 127) || (key == 8))
{
tty_con.cursor--;
tty_con.buffer[tty_con.cursor] = '\0';
tty_Back();
if (tty_con.cursor > 0)
{
tty_con.cursor--;
tty_con.buffer[tty_con.cursor] = '\0';
tty_Back();
}
ev.key = KEY_BACKSPACE;
}
ev.key = KEY_BACKSPACE;
}
else if (key < ' ') // check if this is a control char
{
if (key == '\n')
else if (key < ' ') // check if this is a control char
{
tty_Clear();
tty_con.cursor = 0;
ev.key = KEY_ENTER;
if (key == '\n')
{
tty_Clear();
tty_con.cursor = 0;
ev.key = KEY_ENTER;
}
else continue;
}
else return;
else if (tty_con.cursor < sizeof (tty_con.buffer))
{
// push regular character
ev.key = tty_con.buffer[tty_con.cursor] = key;
tty_con.cursor++;
// print the current line (this is differential)
write(STDOUT_FILENO, &key, 1);
}
if (ev.key) D_PostEvent(&ev);
//tty_FlushIn();
}
else if (tty_con.cursor < sizeof (tty_con.buffer))
{
// push regular character
ev.key = tty_con.buffer[tty_con.cursor] = key;
tty_con.cursor++;
// print the current line (this is differential)
d = write(STDOUT_FILENO, &key, 1);
}
if (ev.key) D_PostEvent(&ev);
//tty_FlushIn();
(void)d;
}
#elif defined (_WIN32)

View file

@ -1297,6 +1297,14 @@ void I_FinishUpdate(void)
#ifdef HWRENDER
else if (rendermode == render_opengl)
{
// Final postprocess step of palette rendering, after everything else has been drawn.
if (HWR_ShouldUsePaletteRendering())
{
HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2);
HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_PALETTE_POSTPROCESS));
HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0);
HWD.pfnUnSetShader();
}
OglSdlFinishUpdate(cv_vidwait.value);
}
#endif
@ -1958,32 +1966,34 @@ void VID_StartupOpenGL(void)
HWD.pfnSetTexture = hwSym("SetTexture",NULL);
HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL);
HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL);
HWD.pfnReadRect = hwSym("ReadRect",NULL);
HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL);
HWD.pfnGClipRect = hwSym("GClipRect",NULL);
HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL);
HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL);
HWD.pfnSetPalette = hwSym("SetPalette",NULL);
HWD.pfnSetTexturePalette= hwSym("SetTexturePalette",NULL);
HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL);
HWD.pfnDrawModel = hwSym("DrawModel",NULL);
HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL);
HWD.pfnSetTransform = hwSym("SetTransform",NULL);
HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);
HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL);
HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL);
HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL);
HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL);
HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL);
HWD.pfnDrawScreenTexture= hwSym("DrawScreenTexture",NULL);
HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL);
HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
HWD.pfnCompileShaders = hwSym("CompileShaders",NULL);
HWD.pfnCleanShaders = hwSym("CleanShaders",NULL);
HWD.pfnInitShaders = hwSym("InitShaders",NULL);
HWD.pfnLoadShader = hwSym("LoadShader",NULL);
HWD.pfnCompileShader = hwSym("CompileShader",NULL);
HWD.pfnSetShader = hwSym("SetShader",NULL);
HWD.pfnUnSetShader = hwSym("UnSetShader",NULL);
HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL);
HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL);
HWD.pfnSetPaletteLookup = hwSym("SetPaletteLookup",NULL);
HWD.pfnCreateLightTable = hwSym("CreateLightTable",NULL);
HWD.pfnClearLightTables = hwSym("ClearLightTables",NULL);
HWD.pfnSetScreenPalette = hwSym("SetScreenPalette",NULL);
vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library

View file

@ -232,7 +232,9 @@ void OglSdlFinishUpdate(boolean waitvbl)
// Sryder: We need to draw the final screen texture again into the other buffer in the original position so that
// effects that want to take the old screen can do so after this
HWR_DrawScreenFinalTexture(realwidth, realheight);
// Generic2 has the screen image without palette rendering brightness adjustments.
// Using that here will prevent brightness adjustments being applied twice.
DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0);
}
EXPORT void HWRAPI(OglSdlSetPalette) (RGBA_t *palette)

View file

@ -227,8 +227,8 @@ void ST_doPaletteStuff(void)
palette = 0;
#ifdef HWRENDER
if (rendermode == render_opengl)
palette = 0; // No flashpals here in OpenGL
if (rendermode == render_opengl && !HWR_ShouldUsePaletteRendering())
palette = 0; // Don't set the palette to a flashpal in OpenGL's truecolor mode
#endif
if (palette != st_palette)
@ -1945,7 +1945,7 @@ static void ST_drawNiGHTSHUD(void)
total_ringcount = stplyr->spheres;
}
if (stplyr->capsule)
if (!P_MobjWasRemoved(stplyr->capsule))
{
INT32 amount;
const INT32 length = 88;
@ -2893,7 +2893,7 @@ void ST_Drawer(void)
//25/08/99: Hurdler: palette changes is done for all players,
// not only player1! That's why this part
// of code is moved somewhere else.
if (rendermode == render_soft)
if (rendermode == render_soft || HWR_ShouldUsePaletteRendering())
#endif
if (rendermode != render_none) ST_doPaletteStuff();

View file

@ -821,10 +821,7 @@ static void W_ReadFileShaders(wadfile_t *wadfile)
{
#ifdef HWRENDER
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
{
HWR_LoadCustomShadersFromFile(numwadfiles - 1, W_FileHasFolders(wadfile));
HWR_CompileShaders();
}
#else
(void)wadfile;
#endif
@ -1171,6 +1168,7 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
numwadfiles++;
W_ReadFileShaders(wadfile);
W_LoadTrnslateLumps(numwadfiles - 1);
W_LoadDehackedLumpsPK3(numwadfiles - 1, mainfile);
W_InvalidateLumpnumCache();
@ -2707,7 +2705,7 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum)
UINT8 *wadData = W_CacheLumpNum(lumpnum, PU_LEVEL);
filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs);
numlumps = ((wadinfo_t *)wadData)->numlumps;
vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL);
vlumps = Z_Calloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL);
// Build the lumps.
for (i = 0; i < numlumps; i++)
@ -2731,7 +2729,7 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum)
break;
numlumps++;
vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL);
vlumps = Z_Calloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL);
for (i = 0; i < numlumps; i++, lumpnum++)
{
vlumps[i].size = W_LumpLength(lumpnum);