Compare commits

...
Author SHA1 Message Date
indev 5a44afcd9f Disable multithreading in R_DrawMaskedList 2025-07-01 16:09:18 +03:00
Alug 3c282b5022 this can use min/max 2025-07-01 14:42:28 +02:00
Alug f4d40bd55f "-Wno-aggregate-return" for c++ 2025-07-01 14:38:42 +02:00
Alug 465fea8bb3 "restrict" macro for c++
since it does not have it, use __restrict instead
2025-06-30 12:18:21 +02:00
Alug d47e20b54e those can be const 2025-06-29 11:44:29 +02:00
Alug 4e9f9b7e0e Revert "add "for_each" to srb2 threadpool"
This reverts commit 604bc40021.
2025-06-27 16:38:19 +02:00
Alug 9650139470 Revert "allocate tiltlighting buffer in R_AllocViewMemory again"
This reverts commit b541de4f8c.
2025-06-27 16:38:16 +02:00
Alug 054a40a4b2 Revert "omit realloc and use unique_ptr for our tiltlighting buffer"
This reverts commit e351c1e62a.
2025-06-27 16:38:13 +02:00
Alug 972ee5cf76 remove erronous BACKSLASH
was from when this was a macro lel
edit: screw you comptime
2025-06-26 20:17:33 +02:00
Gustaf Alhäll aef02cb347 Fix one-pixel wide gaps in tall sprites 2025-06-26 20:09:16 +02:00
Alug 36e485b2a3 move gl portalcullsector check back to the right place lel
oopsie
2025-06-26 15:13:54 +02:00
Alug d23c51e707 mark node as restrict again pointonside 2025-06-26 13:22:17 +02:00
Alug 0db437aadd do some more tiny optimizations
-those can all be declared with restrict
-our ternary clamp macro is slightly faster than std::clamp
2025-06-26 13:22:15 +02:00
Alug e351c1e62a omit realloc and use unique_ptr for our tiltlighting buffer
this makes asan shut up, since those effectively clean up after themselves
2025-06-26 13:22:11 +02:00
Alug b541de4f8c allocate tiltlighting buffer in R_AllocViewMemory again
just removes the ugly stuff in the span drawers
needs to be tested a little, but should be fine
2025-06-26 13:21:56 +02:00
Alug 604bc40021 add "for_each" to srb2 threadpool
this exectures something for EACH thread not some abritatrily choosen ones
2025-06-26 13:21:52 +02:00
Alug be8ddebd80 forgor about the new signal handler oop 2025-06-26 00:39:01 +02:00
Alug b2a36850cb Merge branch 'Saturn-Next' into softwarecrap 2025-06-25 12:47:43 +02:00
Alug 8353c1efdd add toggle for software cyan cut stuff
"softwarecyancut"
this is disabled by default, since some vanilla maps were designed around this
also costs a bit of performance (splat span drawers are slooooow)
2025-06-25 12:47:25 +02:00
Alug d19a2e0912 attempt to make fofs in software always cut cyan pixels
if they do contain cyan pixels lel
kinda meh, and needs a toggle
2025-06-25 12:45:14 +02:00
Alug 07432c0381 turn angle stuff into a switch in R_SetupSkyScale 2025-06-25 12:29:58 +02:00
Alug 4fb3b63152 optimize R_StoreWallRange with cut down version of rendersegloop when a seg is untextured
from srb2, its just a cut down rendersegloop with alot less things to check and such
2025-06-23 19:38:57 +02:00
Alug 85b736620a Merge remote-tracking branch 'origin/Saturn-Next' into Saturn-Next 2025-06-23 19:26:07 +02:00
Alug 9f770993d4 proper init enterprecise 2025-06-23 19:25:50 +02:00
Alug 4bd02ad325 check if player is local here 2025-06-23 19:25:46 +02:00
Alug 6e7b45d15c simplify R_SetupAimingFrame 2025-06-23 19:25:34 +02:00
Alug 99ebca51d5 use const_cast for colfunccopy
idk its from rr idk why it was like this
2025-06-23 19:23:56 +02:00
Alug 24eb888af3 make skytextures support texture offsets in software 2025-06-23 19:20:20 +02:00
Alug 09ce33abb9 just always clamp the non psprite texture column
this may underflow, which the check in the lööp body does not account for
2025-06-23 19:18:11 +02:00
indev 044ff158a1 SF_HIRES is already handled via spritexscale and spriteyscale 2025-06-23 18:37:57 +03:00
Alug 36c68d055c minor optimizations r_things 2025-06-21 18:07:44 +02:00
Alug ddf7d7cdcb use templates for R_ClipWallSegment
actual slight speedup
2025-06-21 18:07:41 +02:00
Alug 38950d580f fix a clang warning 2025-06-20 09:54:20 +02:00
Alug 707701f317 do palette stuff in st_ticker
cleanup and dont call it in normal ogl at all unless palette render with flashpals is enabled
inspired by Nyan-Doom/Woof
2025-06-20 09:54:17 +02:00
Alug 09507d635b remove now unecessary type cast 2025-06-19 17:41:26 +02:00
Alug ab85d6a693 shut the up -Waggregate-return 2025-06-19 17:41:23 +02:00
Alug 5011b17f88 attempt at optimizing drawcolumn drawers a bit more
inspired by dsda/prboom
seems to be super slighty faster
2025-06-19 15:57:21 +02:00
Alug 7bef45f701 Merge remote-tracking branch 'origin/Saturn-Next' into softwarecrap 2025-06-19 15:50:55 +02:00
indev 40cbce8f9f Merge pull request #178 from Indev450/newmakefiles
Port over SRB2´s makefile rewrites + Port Dedicated server build
2025-06-19 16:47:34 +03:00
Alug 70a70084c9 macrofy ogl function pointer setup
should make it a little less annoying to add new functions
2025-06-17 19:21:09 +02:00
indev b6da6359d3 If gamestate resend took too long, abort resynching 2025-06-16 21:43:54 +03:00
Alug 97075ca5c5 remove some code dupe
starting to like those lambda things
2025-06-13 16:08:06 +02:00
Alug e94737945a fix double sided skies per addline clipping code
fixes greencave skybox
hopefully this is it and doesent break anything else sigh
2025-06-13 08:11:45 +02:00
Alug 57f15e0213 R_GenerateBlendTables can be static 2025-06-13 03:23:31 +02:00
Alug 2eae9b197c port the span and column drawer templates + tilted translucent splat drawer
took the liberty to also carry over our optimizations, this is actually slightly faster than what we had before
2025-06-13 03:23:25 +02:00
Alug 68c7620349 Merge branch 'Saturn-Next' into softwarecrap 2025-06-13 00:53:30 +02:00
Alug 7a3faf34e7 move this into an if else
saves us a little work
2025-06-13 00:20:59 +02:00
Alug d401644447 tweak the sky checks even more
apparently koda has a skybox, and checking like this makes it not trigger, lets hope this has no bad side effects Zzz...
2025-06-13 00:20:48 +02:00
Alug dfc349b230 Merge branch 'newmakefiles' into softwarecrap 2025-06-12 23:33:49 +02:00
Alug 687d2bd894 Merge remote-tracking branch 'origin/Saturn' into Saturn-Next 2025-06-12 23:18:45 +02:00
Alug 78b642cf2d Merge pull request #183 from P-AS/mac-fixes
Fix build on macOS
2025-06-12 21:46:39 +01:00
Alug cb3b6ca34b Merge pull request #184 from chromaticpipe/levelinterpolatorjitter
Fix level interpolators jittering during objectplace
2025-06-12 20:46:31 +01:00
Alug ad15bf0ea3 readd some lost comments in r_bsp 2025-06-12 19:48:58 +02:00
Alug 56021ed999 dont compile with software multithread if NOTHREADS/HAVE_THREADS=0
might be useful for smth ig
2025-06-12 19:48:55 +02:00
chromaticpipe 3d22a5906f Fix level interpolators jittering during objectplac 2025-06-12 11:37:25 -05:00
Alug b6d771b48f unnest the skybox scale setup stuff 2025-06-12 17:10:26 +02:00
Alug ab30fb2e5e check if seg has any texture at all
seems to work even better and less "false positives"
also removing some redundant conditons
2025-06-12 17:10:22 +02:00
Alug 618d9e4cdf add lugent to credits 2025-06-11 20:55:26 +02:00
Alug bf78ad9c75 absolute insanity to hopefully fix all sky issues while keeping skyvisible 2025-06-11 20:28:16 +02:00
Alug 918a4e8cd9 add tilted fog span drawer
fixes the red fog blocks on mkrevamp
2025-06-11 17:10:47 +02:00
Alug e90c84c9ac we have a var for that lul 2025-06-11 16:32:36 +02:00
PAS a9209a4887 Include errno.h on macOS 2025-06-10 21:53:43 -04:00
Eidolon 0a3e7ba09f Include poll.h on UNIXCOMMON
Apple was not including poll.h despite needing it.
2025-06-10 21:49:00 -04:00
Alug eb132b08c0 make the check a little more robust + account for slopes a little 2025-06-11 00:31:01 +02:00
Alug 82407c3560 add missing plane bounds check to R_DrawSkyPlane 2025-06-11 00:30:59 +02:00
Alug f1a8210663 another attempt at actually fixing sky issues
absolutely fucking horrible
but this also does account for single sided lines aswell and gets rid of artifacts and perf
2025-06-10 18:33:20 +02:00
Alug 1d722be4bc few smoler optimizations r_segs 2025-06-10 01:21:36 +02:00
Alug 62a660bfe1 maybe this makes perf better somehow 2025-06-10 01:21:34 +02:00
Alug 2984795175 kill the splitscreen lööps from R_RenderPlayerView
this already gets called from within the one that assigns viewssnum which we can just use here
2025-06-09 23:45:02 +02:00
Alug da706d89a5 absolutely disgusting hack for sky issues
instead of homremoval, we draw the fucking skyplane before everything lmao
there probably is a right way to fix this, but im too dumb for that
needs some performance testing, but since i could move the semaphores back, its even better in some instances
2025-06-09 22:59:52 +02:00
Alug a8005d5cec fix portals dying
due to nummasks being too small and causing an overflow
ty hannu!
2025-06-09 20:57:19 +02:00
Alug 793ccff6e6 fix the goddamn portal use after free
https://git.do.srb2.org/STJr/SRB2/-/commit/f536ab34674fb8d3ee262a0009753f552074305c
2025-06-09 19:02:58 +02:00
Alug e7db9bf1fd fix bad copy paste lul 2025-06-09 17:09:57 +02:00
Alug 88d62c93a1 fix SHITPLANESPARENCY and QUINCUNX
maybe
2025-06-09 17:06:31 +02:00
Alug d73532d019 fix some fofs not rendering in software
i did an oopsie in 7.2 X)
2025-06-09 17:06:23 +02:00
Alug 84d3d23936 declare fracstep as const 2025-06-09 17:06:20 +02:00
Alug 717947843b memset those 2025-06-09 17:06:16 +02:00
Alug 968584a316 make skyportals account for how kart sets the viewheight
no we still dont use it
2025-06-09 17:06:14 +02:00
Alug ccd67f621a dont set any texture mapped drawer when fog 2025-06-09 17:06:10 +02:00
Alug 80b301dbbe unnest the overflow_test stuff
its also a ternary now lul
2025-06-09 17:06:07 +02:00
Alug 001e61d39d Merge branch 'Saturn-Next' into softwarecrap 2025-06-09 17:06:02 +02:00
Alug 19c98a436a fix some fofs not rendering in software
i did an oopsie in 7.2 X)
2025-06-09 17:05:42 +02:00
Alug 8dd6d7cfdd fix the fov adjust check
lmao oops
2025-06-09 16:59:00 +02:00
Alug 7456b6e02c Revert "bring back old clipwallsegment stuff"
This reverts commit 6af77afc44.
2025-06-09 04:27:58 +02:00
Alug 5e8096f74c move hom removal to D_Renderview
removes the hwr code dupe and moves this out of the splitscreen loop
2025-06-09 00:21:41 +02:00
Alug 6af77afc44 bring back old clipwallsegment stuff
i just didnt like the flow of the new ones
2025-06-08 21:38:57 +02:00
Alug 42eeb7bdf5 fix the massive slowdown on ante
due to really bad loop layout
std::fill is only cause it looks fancy :3
2025-06-08 21:38:54 +02:00
Alug 6f4b1e5125 fix portals on slopes
idk this is quite the hack, but it works
this adjustment somehow got omitted from srb2 during the portal refactor
2025-06-08 20:03:09 +02:00
Alug 22e65cdda8 readd portalcullsector
+ sprite clipping improvements with portals
2025-06-08 20:03:06 +02:00
Alug 9d342d0f3d fix lightlist memory leak
not sure if we need to copy over the old shit, but this seems to work aswell
2025-06-08 17:24:18 +02:00
Alug 9583bed718 fix da rippled wöter
i hate fixed point maths lmao
2025-06-08 00:43:15 +02:00
Alug b69ce75712 do NOT use Z_ functions in threaded stuff
shit dies
2025-06-08 00:25:03 +02:00
Alug a1cd19b023 make the fov dependant init stuff bit more safe and stuff 2025-06-07 23:54:12 +02:00
Alug 6e50710b25 fix column data colormap shit in R_RenderThickSideRange
too lazy to explain so https://git.do.srb2.org/KartKrew/RingRacers/-/commit/1ccd41c3dbb3132ce7467edf0c12c9d420b189f9
2025-06-07 23:31:51 +02:00
indev 989a971d27 Fix 'C++11 requires a space between literal and string macro' warning 2025-06-07 23:18:55 +03:00
indev 24ee56ce7a ceepeepee 17 :3 2025-06-07 23:15:55 +03:00
Alug 52f99dd9c1 fix span corruption due to wrong types being used
i did not realise srb2 changed this at some point to use fixed_t
2025-06-07 20:05:51 +02:00
Alug 6374fda570 convert i_system to cpp add missing exit for threading errors 2025-06-07 20:05:48 +02:00
Alug cdd2d6323e dont think we need this twice lel 2025-06-07 20:05:03 +02:00
Alug c508a7ea78 smol makefile stuff 2025-06-07 20:05:01 +02:00
Alug 1380a394c7 remove duped declaration 2025-06-07 20:04:58 +02:00
Alug 2c937099d4 this does nothing lel 2025-06-07 20:04:55 +02:00
Alug 0a936b3bba fix le sourcefile 2025-06-07 20:04:52 +02:00
Alug 0a31e0a65e use realloc for batching stuff
seems to strangely speed things up even
didnt think those happen often?
2025-06-07 11:55:52 +02:00
Alug 8627a18452 Merge pull request #182 from chromaticpipe/fixedhelp
Fixed help command
2025-06-07 10:54:36 +01:00
Alug be528adea5 thanks michaelsoft! 2025-06-07 10:21:25 +01:00
James R. 5eb4ed8391 R_FindPlane: fix offsets rotation overflow for non-sloped planes 2025-06-07 11:43:13 +02:00
James R 9a00d30c0c Do not factor height into sprite thickseg sorting 2025-06-07 11:43:10 +02:00
James R 71237c5e11 Check that top of sprite is above plane or bottom is below
This fixes slightly raised fofs drawing on top of sprites that should be in
front of them. Previously would check that the bottom of the object was above
the plane. Now also uses sprite offsets like the fof seg sorting does.
2025-06-07 11:43:07 +02:00
Alug 9c6e32a1ab HACK: dont pass wflags to c++
silences some annoying compiler complaints lel
2025-06-07 11:43:04 +02:00
Alug 1bc18801c8 cleanup the software drawers even more + unroll them
looks pretty clean now, not sure if i want to port the templates, this is good enough for now
2025-06-07 11:43:01 +02:00
Alug 221f2a956e tiny optimizations 2025-06-07 11:42:58 +02:00
Alug b450abdf4d simplify R_ExpandPlane 2025-06-07 11:42:55 +02:00
Alug d36eed3c09 convert r_segs to ceepeepee + overflow fix from RR R_DrawRepeatMaskedColumn
+ alot of cleanup
should more or less function the same, just alot less messy
2025-06-07 11:42:52 +02:00
Alug 43ee791d4a fix slopes and slope flat alignment
software slopes finally are sane........
fixes certain maps like stardust speedway looking like complete butt
need to test ogl, not sure if theres any real change there
2025-06-07 11:42:48 +02:00
Alug c921945922 cleanup software drawer handling stuff
mostly ported from rr
is alot more readable and less confusing
2025-06-07 11:42:45 +02:00
Alug 5f8c77e752 test: allow multithreading for masked planes
quite a neat speedup on some maps
needs testing
2025-06-07 01:20:52 +02:00
Alug 064db977aa HACK: move semaphores into the drawplane loop, to fix a few visual glitches
a bit of slowdown, but i have no clue what exactly causes shit, so this is the best solution for now i guess
2025-06-07 01:20:48 +02:00
Alug 5868cd9777 make drawcolum lightlists use realloc again lel
otherwise theres a crapton of overlapping memory lel
2025-06-07 01:20:44 +02:00
Alug b0ddde996a forgor this from removing screen size static array stuff lel 2025-06-07 01:20:41 +02:00
Alug e03c3766f0 forgor to free the mask heads lel 2025-06-07 01:20:37 +02:00
Alug 953c0d7451 convert r_things to ceepeepee 2025-06-07 01:20:34 +02:00
Alug 97b303c362 split skin stuff from r_things into r_skins
what a mess
2025-06-07 01:20:31 +02:00
Alug 2ffe736a20 smol cleanup 2025-06-07 01:20:28 +02:00
Alug 21f2032f34 save smol amount of fixed to double conversions in R_StoreWallRange
also adds those as actual functions in case we wanna use it for smth else
2025-06-06 17:37:55 +02:00
Alug 2f66207205 make this less ugly 2025-06-06 16:55:38 +02:00
Alug 5a14b09c1f cache ds->transmap for translucent span drawers
super slight speedup
2025-06-06 16:35:26 +02:00
Alug 7e9da92dbe dont redundantly clamp the sprites texturecolumn
we already take care of this in the lööp header
2025-06-06 16:35:23 +02:00
Alug a27550b95b fix R_ProjectSprite clipping checks overflowing
was causing sprites to disappear in some angles
2025-06-06 14:43:03 +02:00
Alug 556883487d optimize software hud drawing
from srb2classic adjusted to our drawers
2025-06-06 01:17:36 +02:00
Alug 96f8533479 dont check for wraps on 0 height textures in column drawers
slight speedup thx srb2classic!
2025-06-06 01:04:20 +02:00
Alug f3cca27448 cache vid.width in the column drawers
shit was really slow lel
2025-06-06 00:55:23 +02:00
indev 252563725d Make tiltlighting buffer thread_local 2025-06-06 01:42:15 +03:00
indev 9a934a55e2 Revert "ok fuck you tiltlighting static buffer it is"
This reverts commit 2a023246be.
2025-06-06 01:39:51 +03:00
Alug f07d5d381e fix the goddamn boolean 2025-06-06 00:19:23 +02:00
Alug 3faab66ef4 add toggle for software multithread 2025-06-06 00:04:42 +02:00
Alug 2a023246be ok fuck you tiltlighting static buffer it is 2025-06-06 00:04:39 +02:00
Alug 006e7fe8f8 move this 2025-06-06 00:04:36 +02:00
Alug 1a7ff21a04 fix some warnings and plane ripple 2025-06-06 00:04:33 +02:00
Alug 98cb0fdcb2 fix slopes and other shit 2025-06-06 00:04:30 +02:00
indev 1fd7e9cdac Add -lpthread into libs and cxxopts into c++ compilation flags 2025-06-06 00:04:27 +02:00
indev 0a2eac4d3a Add ifdef __cplusplus into hardware/hw_main.h 2025-06-06 00:04:24 +02:00
Alug 9ac6fffd4d busted ass multithreading for le soft 2025-06-06 00:04:19 +02:00
Alug da20f4a087 Merge branch 'newmakefiles' into softwarecrap 2025-06-06 00:04:14 +02:00
Alug dbf822ced9 dont draw precip in the skybox lel 2025-06-05 15:05:29 +02:00
Alug 095842f4aa smol cleanup the splat drawers
didnt knew we actually use em so kinda didnt care lel
2025-06-05 15:00:35 +02:00
Alug 8c290d7597 kill static buffer for tiltlighting, again
kinda ugly but gets the job done lel
2025-06-05 14:48:50 +02:00
Alug 8a6f4db9af fix precip not drawing 2025-06-05 14:48:47 +02:00
Alug 99186a86db port masked drawlists for software + portal visplanes
Note: need to check if we gotta readd portalcullsector for ogl portals, technically this is alot faster and fixes the occasional portal disappearing, but may introduce occasional visual bugs
2025-06-05 14:48:44 +02:00
Alug c67bf97f7b unglobalize drawspandata 2025-06-05 14:48:41 +02:00
Alug 33a1540fcd unglobalise drawcolumndata
from RRs multithread
will follow up with spandata
2025-06-05 14:48:38 +02:00
Alug 529b0d643a delet dc_hires 2025-06-05 01:41:55 +02:00
Alug 4576efbe5c remove FIXMEs from draw column stuff 2025-06-05 01:27:34 +02:00
Alug 185375ece1 use ternaries for column clamp
it is slightly faster for me lel
also lets us get rid of an extra variable
npow2min is also declared static as its always -1
2025-06-05 01:25:33 +02:00
Alug d11521954e move those around + remove NOWATER ifdef 2025-06-05 01:01:31 +02:00
Alug 41c4300ec2 split r_draw8 into r_drawcolumn and r_drawspan
+ remove the _8 from the "namespace" since we dont have highcolor stuff
2025-06-05 00:52:53 +02:00
Alug 51d5023f29 those can be just "while" lööps 2025-06-05 00:44:59 +02:00
Alug d2878f8834 set MAXVIDWIDTH and MAXVIDHEIGHT to 8192
should accomidate absolutely everything
2025-06-04 23:03:17 +02:00
Alug 7808159d23 get rid of static screen size buffers, alloc em to current screen size instead
mostly taken from srb2s any-resolution branch
2025-06-04 23:03:14 +02:00
Alug e759431948 clamp shit so vhs effect doesent do oob writes on some resolutions
shoddy way but fuckit
2025-06-04 20:46:12 +02:00
Alug 268ccce955 move ripple blit stuff into own function 2025-06-04 20:00:06 +02:00
Alug f2d3432bf5 make software ripple splitscreen checks less awful to look at 2025-06-04 18:48:33 +02:00
Alug 2da89f1946 remove ylookup, columnofs and topleft lookups
move screens array to "vid" struct
remove a bunch of unused stuff

this speeds up 4 player splitscreen ever so slighty
mostly just alot cleaner than the mess it was before
2025-06-04 15:55:46 +02:00
Alug 6153733df4 unroll span drawer loops 2025-06-04 15:55:43 +02:00
Alug d280b39f9f use floats flor slope drawing
idea from srb2classic
2025-06-04 15:55:40 +02:00
indev 236e7b8d45 Fix game rendering only first splitscreen player in opengl 2025-06-04 03:57:54 +03:00
chromaticpipe dcccf672c9 Truncate trailing zeroes in float CVars 2025-06-03 13:18:02 -05:00
Alug 03f81bed16 dont initialise those twice lol 2025-06-03 20:00:52 +02:00
chromaticpipe fc51c1ba88 Fix help command for CV_FLOAT CVars 2025-06-03 11:38:46 -05:00
indev d50c1ab6d7 dedi's do run got_mapcmd :p 2025-06-02 14:21:34 +03:00
Alug 984c2ff8d6 Merge pull request #175 from chromaticpipe/serverinfo
Display server information before connecting to it
2025-06-01 21:03:19 +01:00
chromaticpipe 74646acdca Options. 2025-05-31 16:27:34 -05:00
indev 45ffe87ba6 Add new music credit draw style, 'songcredits Box' 2025-05-31 22:27:17 +03:00
Alug 37eb8cfa57 shut up curl im already long 2025-05-31 21:01:57 +02:00
Alug a0f903f162 i like switches mhhhm 2025-05-31 21:01:53 +02:00
Alug f1f0782256 fix memoryleak in pk3 verify functions 2025-05-31 17:30:19 +02:00
Alug 0e9a825f63 some crap from ceepeepeecheck 2025-05-31 17:27:07 +02:00
Alug 5c53a90eea hack: reset musiccredits when changing gamestate
otherwise they may persist if theyve been currently displayed
2025-05-31 16:20:58 +02:00
Alug 55c6ba6d12 fix awayview join crash
player->awayviewmobj may not exist yet in some cases
2025-05-31 15:57:20 +02:00
Alug 6617382f54 Revert "reset the palette earlier during levelload"
This reverts commit 5e532a76cf.
2025-05-30 23:59:08 +02:00
chromaticpipe dd499a410f Very bad gamepad support 2025-05-30 13:30:47 -05:00
chromaticpipe c04ba992a7 Forgort something 2025-05-30 13:26:27 -05:00
chromaticpipe 27c053cd48 Add Server info screen, ported from SRB2Classic 2025-05-30 13:23:36 -05:00
Alug 7d68c0598c Fix underflow in consistancy checking code
https://git.srb2.org/Hanicef/SRB2Classic/-/commit/9f5686ef48956cd64ef92f737e59cbbaa27d8cf9
2025-05-30 02:54:48 +02:00
Alug 201c725dc7 cleanup d_main a little 2025-05-30 02:54:45 +02:00
Alug 57b2316c42 didnt mean to change this lel 2025-05-29 19:01:19 +02:00
Alug fe682a8071 only make screentexture for postprocess if we need to
gives quite a neat perfboost on the gpu side
2025-05-29 19:01:16 +02:00
Alug bf44a054a1 move HWR_GetTexturePalette calls
to after early returns/where they are used
2025-05-29 18:17:26 +02:00
Alug eca9c60d9b call HWR_LoadMapTextures in paletterender toggle callback
from srb2 pr
2025-05-29 18:17:23 +02:00
Alug cf42c35b9f add mo checks to automap stuff 2025-05-29 13:40:57 +02:00
Alug a364068abb add a bunch of checks for if G_BuildMapTitle returns NULL 2025-05-29 13:40:53 +02:00
Alug e88093d9cf no need for an else here 2025-05-29 12:30:07 +02:00
Alug 5e532a76cf reset the palette earlier during levelload
generally make this behave like srb2/rr again
2025-05-29 12:30:05 +02:00
Alug fb9c459269 readd cubeapply check here 2025-05-29 12:30:00 +02:00
Alug a6898bd1cd this memset is incorrect and does nothing 2025-05-28 22:12:00 +02:00
Alug ff474d18ee remove this
prob wrong assumption, our netcode sucks massive ass
2025-05-28 21:44:38 +02:00
Alug f15d3be263 forgor the hw state lel 2025-05-28 18:39:20 +02:00
Alug 19e5366c5b add wireframe mode for ogl 2025-05-28 18:31:55 +02:00
Alug 346dee019c fix compiler warning bout playeringame 2025-05-28 18:31:37 +02:00
Alug 18914f22f2 remove crappy memcpy redifine from md5 2025-05-28 18:31:33 +02:00
Alug 1219ecf818 check for 32bit with __SIZEOF_POINTER__ for precip drawdistance
thx @chromaticpipe for the tip!
2025-05-28 16:27:40 +02:00
Alug b6923d0d0d readd flexible array for softwarepatch columnofs
how did this ever work lel
2025-05-28 16:21:57 +02:00
132 changed files with 8628 additions and 6870 deletions

No files matched your search

+7 -19
View File
@@ -181,7 +181,8 @@ objdir:=$(makedir)/objs
# very sophisticated dependency
sources+=\
$(call List,Sourcefile)
$(call List,Sourcefile)\
$(call List,core/Sourcefile)
sources+=\
$(call List,blua/Sourcefile)
@@ -262,12 +263,10 @@ opts+=$(debug_opts)
opts+=$(foreach v,$(passthru_opts),$(if $($(v)),-D$(v)))
opts+=$(WFLAGS) $(CPPFLAGS) $(CFLAGS)
libs+=$(LDFLAGS) -lstdc++
asflags:=$(ASFLAGS) -x assembler-with-cpp
cxxopts:=$(opts) $(CXXFLAGS) -std=c++17
cxxopts:=$(opts)
cxxopts+=-std=c++17
cxxopts+=$(CXXFLAGS)
libs+=$(LDFLAGS) -lstdc++ -lpthread
asflags:=$(ASFLAGS) -x assembler-with-cpp
cc=$(CC)
cxx=$(CXX)
@@ -288,6 +287,7 @@ ifndef SILENT
ifndef MAKE_RESTARTS
ifndef destructive
$(shell $(CC) -v)
#$(shell $(CXX) -v)
define flags =
SHELL ..... $(SHELL)
@@ -315,6 +315,7 @@ endif
LD:=$(CC)
cc:=$(cc) $(opts)
cxx:=$(cxx) $(cxxopts)
ifdef UPX
upx=$(UPX) $(UPX_OPTS)
endif
@@ -377,19 +378,6 @@ endif
$(.)$(cc) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
endef
# dependency recipe template (C++)
# 1: source file suffix
# 2: extra flags to gcc
define _recipecxx =
$(depdir)/%.d : %.$(1) | $$$$(@D)/
ifndef WINDOWSHELL
ifdef Echo_name
@printf '%-20.20s\r' $$<
endif
endif
$(.)$(cxx) -MM -MF $$@ -MT $(objdir)/$$*.o $(2) $$<
endef
$(eval $(call _recipe,c))
$(eval $(call _recipe,cpp))
$(eval $(call _recipe,s,$(asflags)))
-2
View File
@@ -4,8 +4,6 @@ sources+=$(call List,dedicated/Sourcefile)
opts+=-DDEDICATED
libs+=-lpthread
ifdef MINGW
libs+=-mconsole
endif
+1 -1
View File
@@ -10,8 +10,8 @@
makedir:=$(makedir)/SDL
sources+=$(call List,sdl/Sourcefile)
opts+=-DDIRECTFULLSCREEN -DHAVE_SDL
sources+=$(call List,sdl/Sourcefile)
NOUPNP=1
+3
View File
@@ -16,6 +16,9 @@ $(foreach v,$(join $(wordlist 2,$(_n),- $(gcc_versions)),\
$(and $(findstring =,$(v)),\
$(eval $(call _predecessor,$(subst =, ,$(v))))))
# aggregate returns seem to happen alot in c++ so just supress em lel
CXXFLAGS+= -Wno-aggregate-return
# -W -Wno-unused
ifdef GCC150
+5 -4
View File
@@ -49,14 +49,15 @@ r_bsp.c
r_data.c
r_draw.c
r_fps.c
r_main.c
r_main.cpp
r_patch.c
r_patchrotation.c
r_plane.c
r_segs.c
r_plane.cpp
r_segs.cpp
r_skins.c
r_sky.c
r_splats.c
r_things.c
r_things.cpp
r_portal.c
p_ceilng.c
p_enemy.c
+8 -4
View File
@@ -197,7 +197,7 @@ static fixed_t scale_mtof = (fixed_t)INITSCALEMTOF;
// used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
static fixed_t scale_ftom;
static player_t *plr; // the player represented by an arrow
static player_t *plr = NULL; // the player represented by an arrow
static boolean followplayer = true; // specifies whether to follow the player around
@@ -237,7 +237,7 @@ static inline void AM_restoreScaleAndLoc(void)
m_x = old_m_x;
m_y = old_m_y;
}
else
else if (plr && plr->mo)
{
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;
@@ -318,7 +318,8 @@ static void AM_initVariables(void)
break;
plr = &players[pnum];
if (plr != NULL && plr->mo != NULL)
if (plr && plr->mo)
{
m_x = (plr->mo->x >> FRACTOMAPBITS) - m_w/2;
m_y = (plr->mo->y >> FRACTOMAPBITS) - m_h/2;
@@ -340,7 +341,7 @@ static void AM_FrameBufferInit(void)
f_x = f_y = 0;
f_w = vid.width;
f_h = vid.height;
am_buf = screens[0];
am_buf = vid.screens[0];
}
//
@@ -597,6 +598,9 @@ static inline void AM_changeWindowScale(void)
static inline void AM_doFollowPlayer(void)
{
if (!plr || !plr->mo)
return;
if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
{
m_x = FTOM(MTOF(plr->mo->x >> FRACTOMAPBITS)) - m_w/2;
-1
View File
@@ -46,7 +46,6 @@ INT32 VID_SetMode(INT32 modenum)
vid.modenum = 0;
vid.width = 320;
vid.height = 240;
vid.bpp = 1;
vid.buffer = android_surface;
return 0;
}
+2
View File
@@ -28,6 +28,7 @@
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = (void *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITESINT8(p,b) do { SINT8 *p_tmp = (void *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEINT16(p,b) do { INT16 *p_tmp = (void *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = (void *)p; const UINT16 tv = ( UINT16)(b); memcpy(p, &tv, sizeof( UINT16)); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEINT32(p,b) do { INT32 *p_tmp = (void *)p; const INT32 tv = ( INT32)(b); memcpy(p, &tv, sizeof( INT32)); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = (void *)p; const UINT32 tv = ( UINT32)(b); memcpy(p, &tv, sizeof( UINT32)); p_tmp++; p = (void *)p_tmp; } while (0)
@@ -38,6 +39,7 @@
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; *p_tmp = ( UINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; *p_tmp = ( SINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; p = (void *)p_tmp; } while (0)
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(b); p_tmp++; p = (void *)p_tmp; } while (0)
+35 -15
View File
@@ -240,7 +240,6 @@ void COM_ImmedExecute(const char *ptext)
while (i < strlen(ptext))
{
quotes = 0;
for (j = 0; i < strlen(ptext); i++,j++)
{
@@ -817,12 +816,17 @@ static void COM_Help_f(void)
cvar = CV_FindVar(help);
if (cvar)
{
boolean floatmode = false;
const char *cvalue = NULL;
CONS_Printf("\x82""Variable %s:\n", cvar->name);
CONS_Printf(M_GetText(" flags: "));
if (cvar->flags & CV_SAVE)
CONS_Printf("AUTOSAVE ");
if (cvar->flags & CV_FLOAT)
{
CONS_Printf("FLOAT ");
floatmode = true;
}
if (cvar->flags & CV_NETVAR)
CONS_Printf("NETVAR ");
if (cvar->flags & CV_CALL)
@@ -832,30 +836,43 @@ static void COM_Help_f(void)
CONS_Printf("\n");
if (cvar->PossibleValue)
{
if (!stricmp(cvar->PossibleValue[0].strvalue, "MIN") && !stricmp(cvar->PossibleValue[1].strvalue, "MAX"))
{
CONS_Printf(" range from %d to %d\n", cvar->PossibleValue[0].value,
cvar->PossibleValue[1].value);
i = 2;
}
if (!stricmp(cvar->PossibleValue[0].strvalue, "MIN") && !stricmp(cvar->PossibleValue[1].strvalue, "MAX"))
{
if (floatmode)
{
float fu = FIXED_TO_FLOAT(cvar->PossibleValue[0].value);
float ck = FIXED_TO_FLOAT(cvar->PossibleValue[1].value);
CONS_Printf(" range from %ld%s to %ld%s\n",
(long)fu, M_Ftrim(fu),
(long)ck, M_Ftrim(ck));
}
else
CONS_Printf(" range from %d to %d\n", cvar->PossibleValue[0].value,
cvar->PossibleValue[1].value);
i = 2;
}
{
const char *cvalue = NULL;
//CONS_Printf(M_GetText(" possible value : %s\n"), cvar->name);
while (cvar->PossibleValue[i].strvalue)
{
CONS_Printf(" %-2d : %s\n", cvar->PossibleValue[i].value,
cvar->PossibleValue[i].strvalue);
if (floatmode)
CONS_Printf(" %-2f : %s\n", FIXED_TO_FLOAT(cvar->PossibleValue[i].value),
cvar->PossibleValue[i].strvalue);
else
CONS_Printf(" %-2d : %s\n", cvar->PossibleValue[i].value,
cvar->PossibleValue[i].strvalue);
if (cvar->PossibleValue[i].value == cvar->value)
cvalue = cvar->PossibleValue[i].strvalue;
i++;
}
if (cvalue)
CONS_Printf(" Current value: %s\n", cvalue);
else
CONS_Printf(" Current value: %d\n", cvar->value);
}
}
if (cvalue)
CONS_Printf(" Current value: %s\n", cvalue);
else if (cvar->string)
CONS_Printf(" Current value: %s\n", cvar->string);
else
CONS_Printf(" Current value: %d\n", cvar->value);
}
@@ -1026,7 +1043,10 @@ static void COM_Add_f(void)
}
if (( cvar->flags & CV_FLOAT ))
CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2))));
{
float n =FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2));
CV_Set(cvar, va("%ld%s", (long)n, M_Ftrim(n)));
}
else
CV_AddValue(cvar, atoi(COM_Argv(2)));
}
+8
View File
@@ -13,6 +13,10 @@
#ifndef __COMMAND_H__
#define __COMMAND_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include "doomdef.h"
@@ -189,4 +193,8 @@ UINT8 CV_CheatsEnabled(void);
// Returns cvar by name. Exposed here for Lua.
consvar_t *CV_FindVar(const char *name);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __COMMAND_H__
-7
View File
@@ -1321,13 +1321,6 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...)
//
void CONS_Error(const char *msg)
{
#ifdef RPC_NO_WINDOWS_H
if (!graphics_started)
{
MessageBoxA(vid.WndParent, msg, "SRB2Kart Warning", MB_OK);
return;
}
#endif
CONS_Printf("\x82%s", msg); // write error msg in different colour
CONS_Printf(M_GetText("Press ENTER to continue\n"));
+1
View File
@@ -0,0 +1 @@
target_sourcefile(cpp)
+2
View File
@@ -0,0 +1,2 @@
memory.cpp
thread_pool.cpp
+71
View File
@@ -0,0 +1,71 @@
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
// Copyright (C) 2024 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
#include "memory.h"
#include <array>
#include <new>
#include "../z_zone.h"
namespace
{
class LinearMemory
{
size_t size_;
size_t height_;
void* memory_;
public:
constexpr explicit LinearMemory(size_t size) noexcept;
void* allocate(size_t size);
void reset() noexcept;
};
constexpr LinearMemory::LinearMemory(size_t size) noexcept : size_(size), height_{0}, memory_{nullptr} {}
void* LinearMemory::allocate(size_t size)
{
size_t aligned_size = (size + 15) & ~15;
if (height_ + aligned_size > size_)
{
throw std::bad_alloc();
}
if (memory_ == nullptr)
{
memory_ = Z_Malloc(size_, PU_STATIC, nullptr);
}
void* ptr = (void*)((uintptr_t)(memory_) + height_);
height_ += aligned_size;
return ptr;
}
void LinearMemory::reset() noexcept
{
height_ = 0;
}
} // namespace
static LinearMemory g_frame_memory {4 * 1024 * 1024};
void* Z_Frame_Alloc(size_t size)
{
return g_frame_memory.allocate(size);
}
void Z_Frame_Reset()
{
g_frame_memory.reset();
}
+32
View File
@@ -0,0 +1,32 @@
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
// Copyright (C) 2024 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
#ifndef __SRB2_CORE_MEMORY_H__
#define __SRB2_CORE_MEMORY_H__
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif // __cpluspplus
/// @brief Allocate a block of memory with a lifespan of the current main-thread frame.
/// This function is NOT thread-safe, but the allocated memory may be used across threads.
/// @return a pointer to a block of memory aligned with libc malloc alignment, or null if allocation fails
void* Z_Frame_Alloc(size_t size);
/// @brief Resets per-frame memory. Not thread safe.
void Z_Frame_Reset(void);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // __SRB2_CORE_MEMORY_H__
+192
View File
@@ -0,0 +1,192 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
// This class is derived from Conor Williams' implementation of a concurrent deque
// https://github.com/ConorWilliams/ConcurrentDeque
// Copyright (C) 2021 Conor Williams
// The original version was for C++23. This one has been shrunk slightly and adapted to our conventions.
#ifndef __SRB2_CORE_SPMC_QUEUE_HPP__
#define __SRB2_CORE_SPMC_QUEUE_HPP__
#include <array>
#include <atomic>
#include <cstddef>
#include <memory>
#include <optional>
//#include <tracy/tracy/Tracy.hpp>
#include "../cxxutil.hpp"
namespace srb2
{
template <typename T>
class SpMcQueue
{
struct RingBuff {
public:
explicit RingBuff(int64_t cap) : _cap{cap}, _mask{cap - 1}
{
SRB2_ASSERT(cap && (!(cap & (cap - 1))) && "Capacity must be buf power of 2!");
_buff = std::unique_ptr<T[]>(new T[_cap]);
}
std::int64_t capacity() const noexcept { return _cap; }
// Store (copy) at modulo index
void store(int64_t i, T&& x) noexcept
{
_buff[i & _mask] = std::move(x);
}
// Load (copy) at modulo index
T load(int64_t i) const noexcept
{
return _buff[i & _mask];
}
// Allocates and returns a new ring buffer, copies elements in range [b, t) into the new buffer.
RingBuff* resize(std::int64_t b, std::int64_t t) const
{
//ZoneScoped;
RingBuff* ptr = new RingBuff{2 * _cap};
for (std::int64_t i = t; i != b; ++i) {
ptr->store(i, load(i));
}
return ptr;
}
private:
int64_t _cap; // Capacity of the buffer
int64_t _mask; // Bit mask to perform modulo capacity operations
std::unique_ptr<T[]> _buff;
};
alignas(64) std::atomic<int64_t> bottom_;
alignas(64) std::atomic<int64_t> top_;
alignas(64) std::atomic<RingBuff*> buffer_;
std::vector<std::unique_ptr<RingBuff>> garbage_;
public:
SpMcQueue(size_t capacity) : bottom_(0), top_(0), buffer_(new RingBuff(capacity))
{
garbage_.reserve(32);
}
~SpMcQueue() noexcept
{
delete buffer_.load(std::memory_order_relaxed);
};
size_t size() const noexcept
{
int64_t bottom = bottom_.load(std::memory_order_relaxed);
int64_t top = top_.load(std::memory_order_relaxed);
return static_cast<size_t>(bottom >= top ? bottom - top : 0);
}
bool empty() const noexcept
{
return size() == 0;
}
void push(T&& v) noexcept
{
int64_t bottom = bottom_.load(std::memory_order_relaxed);
int64_t top = top_.load(std::memory_order_acquire);
RingBuff* buf = buffer_.load(std::memory_order_relaxed);
if (buf->capacity() < (bottom - top) + 1)
{
// Queue is full, build a new one
RingBuff* newbuf = buf->resize(bottom, top);
garbage_.emplace_back(buf);
buffer_.store(newbuf, std::memory_order_relaxed);
buf = newbuf;
}
// Construct new object, this does not have to be atomic as no one can steal this item until after we
// store the new value of bottom, ordering is maintained by surrounding atomics.
buf->store(bottom, std::move(v));
std::atomic_thread_fence(std::memory_order_release);
bottom_.store(bottom + 1, std::memory_order_relaxed);
}
std::optional<T> pop() noexcept
{
int64_t bottom = bottom_.load(std::memory_order_relaxed) - 1;
RingBuff* buf = buffer_.load(std::memory_order_relaxed);
bottom_.store(bottom, std::memory_order_relaxed); // Stealers can no longer steal
std::atomic_thread_fence(std::memory_order_seq_cst);
int64_t top = top_.load(std::memory_order_relaxed);
if (top <= bottom)
{
// Non-empty deque
if (top == bottom)
{
// The last item could get stolen, by a stealer that loaded bottom before our write above
if (!top_.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed))
{
// Failed race, thief got the last item.
bottom_.store(bottom + 1, std::memory_order_relaxed);
return std::nullopt;
}
bottom_.store(bottom + 1, std::memory_order_relaxed);
}
// Can delay load until after acquiring slot as only this thread can push(), this load is not
// required to be atomic as we are the exclusive writer.
return buf->load(bottom);
}
else
{
bottom_.store(bottom + 1, std::memory_order_relaxed);
return std::nullopt;
}
}
std::optional<T> steal() noexcept
{
int64_t top = top_.load(std::memory_order_acquire);
std::atomic_thread_fence(std::memory_order_seq_cst);
int64_t bottom = bottom_.load(std::memory_order_acquire);
if (top < bottom)
{
// Must load *before* acquiring the slot as slot may be overwritten immediately after acquiring.
// This load is NOT required to be atomic even-though it may race with an overrite as we only
// return the value if we win the race below garanteeing we had no race during our read. If we
// loose the race then 'x' could be corrupt due to read-during-write race but as T is trivially
// destructible this does not matter.
T x = buffer_.load(std::memory_order_consume)->load(top);
if (!top_.compare_exchange_strong(top, top + 1, std::memory_order_seq_cst, std::memory_order_relaxed))
{
return std::nullopt;
}
return x;
}
else
{
return std::nullopt;
}
}
};
} // namespace srb2
#endif // __SRB2_CORE_SPMC_QUEUE_HPP__
+255
View File
@@ -0,0 +1,255 @@
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
// Copyright (C) 2024 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
#ifndef __SRB2_CORE_STATIC_VEC_HPP__
#define __SRB2_CORE_STATIC_VEC_HPP__
#include <array>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <stdexcept>
#include <type_traits>
#include "../cxxutil.hpp"
namespace srb2
{
template <typename T, size_t Limit>
class StaticVec;
template <typename T, size_t Limit>
class StaticVec
{
std::array<T, Limit> arr_ {{}};
size_t size_ = 0;
public:
using value_type = T;
constexpr StaticVec() {}
StaticVec(const StaticVec& rhs)
{
for (size_t i = size_; i > 0; i--)
{
arr_[i] = T();
}
size_ = rhs.size();
for (size_t i = 0; i < size_; i++)
{
arr_[i] = rhs.arr_[i];
}
}
StaticVec(StaticVec&& rhs) noexcept(std::is_nothrow_move_assignable_v<T>)
{
for (size_t i = size_; i > 0; i--)
{
arr_[i] = T();
}
size_ = rhs.size();
for (size_t i = 0; i < size_; i++)
{
arr_[i] = std::move(rhs.arr_[i]);
}
while (rhs.size() > 0)
{
rhs.pop_back();
}
}
constexpr StaticVec(std::initializer_list<T> list) noexcept(std::is_nothrow_move_assignable_v<T>)
{
size_ = list.size();
size_t i = 0;
for (auto itr = list.begin(); itr != list.end(); itr++)
{
arr_[i] = *itr;
i++;
}
}
~StaticVec() = default;
StaticVec& operator=(const StaticVec& rhs)
{
for (size_t i = size_; i > 0; i--)
{
arr_[i] = T();
}
size_ = rhs.size();
for (size_t i = 0; i < size_; i++)
{
arr_[i] = rhs.arr_[i];
}
return *this;
}
StaticVec& operator=(StaticVec&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>)
{
for (size_t i = size_; i > 0; i--)
{
arr_[i] = T();
}
size_ = rhs.size();
for (size_t i = 0; i < size_; i++)
{
arr_[i] = std::move(rhs.arr_[i]);
}
while (rhs.size() > 0)
{
rhs.pop_back();
}
return *this;
}
void push_back(const T& value) { arr_[size_++] = value; }
void pop_back() { arr_[--size_] = T(); }
void resize(size_t size, T value = T())
{
if (size >= Limit)
{
throw std::length_error("new size >= Capacity");
}
if (size == size_)
{
return;
}
else if (size < size_)
{
while (size_ > size)
{
pop_back();
}
}
else
{
while (size_ < size)
{
push_back(value);
}
}
}
void clear()
{
arr_ = {{}};
size_ = 0;
}
using iterator = typename std::array<T, Limit>::iterator;
using const_iterator = typename std::array<T, Limit>::const_iterator;
constexpr iterator begin() noexcept { return arr_.begin(); }
constexpr const_iterator begin() const noexcept { return arr_.cbegin(); }
constexpr const_iterator cbegin() const noexcept { return arr_.cbegin(); }
constexpr iterator end() noexcept { return std::next(arr_.begin(), size_); }
constexpr const_iterator end() const noexcept { return cend(); }
constexpr const_iterator cend() const noexcept { return std::next(arr_.cbegin(), size_); }
constexpr std::reverse_iterator<iterator> rbegin() noexcept { return std::reverse_iterator(this->end()); }
constexpr std::reverse_iterator<const_iterator> crbegin() const noexcept { return std::reverse_iterator(this->cend()); }
constexpr std::reverse_iterator<iterator> rend() noexcept { return std::reverse_iterator(this->begin()); }
constexpr std::reverse_iterator<const_iterator> crend() const noexcept { return std::reverse_iterator(this->cbegin()); }
constexpr bool empty() const noexcept { return size_ == 0; }
constexpr size_t size() const noexcept { return size_; }
constexpr size_t capacity() const noexcept { return Limit; }
constexpr size_t max_size() const noexcept { return Limit; }
constexpr T& operator[](size_t index) noexcept { return arr_[index]; }
T& at(size_t index)
{
if (index >= size_)
{
throw std::out_of_range("index >= size");
}
return this[index];
}
constexpr const T& operator[](size_t index) const noexcept { return arr_[index]; }
const T& at(size_t index) const
{
if (index >= size_)
{
throw std::out_of_range("index >= size");
}
return this[index];
}
T& front() { return *arr_[0]; }
T& back() { return *arr_[size_ - 1]; }
};
} // namespace srb2
template <typename T, size_t L1, size_t L2>
bool operator==(const srb2::StaticVec<T, L1>& lhs, const srb2::StaticVec<T, L2>& rhs)
{
const size_t size = lhs.size();
if (size != rhs.size())
{
return false;
}
for (size_t i = 0; i < lhs; i++)
{
if (rhs[i] != lhs[i])
{
return false;
}
}
return true;
}
template <typename T, size_t L1, size_t L2>
bool operator!=(const srb2::StaticVec<T, L1>& lhs, const srb2::StaticVec<T, L2>& rhs)
{
return !(lhs == rhs);
}
template <typename T, size_t Limit>
struct std::hash<srb2::StaticVec<T, Limit>>
{
size_t operator()(const srb2::StaticVec<T, Limit>& input) const
{
constexpr size_t prime = sizeof(size_t) == 8 ? 0x00000100000001B3 : 0x01000193;
constexpr size_t basis = sizeof(size_t) == 8 ? 0xcbf29ce484222325 : 0x811c9dc5;
size_t ret = basis;
for (auto itr = input.begin(); itr != input.end(); itr++)
{
ret = (ret * prime) ^ std::hash<T>(*itr);
}
return ret;
}
};
#endif // __SRB2_CORE_STATIC_VEC_HPP__
+346
View File
@@ -0,0 +1,346 @@
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
// Copyright (C) 2024 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
#include "thread_pool.h"
#include <algorithm>
#include <condition_variable>
#include <exception>
#include <mutex>
#include <string>
#include <system_error>
//#include <fmt/format.h>
//#include <tracy/tracy/Tracy.hpp>
#include "../cxxutil.hpp"
#include "../m_argv.h"
using namespace srb2;
static void do_work(ThreadPool::Task& work)
{
try
{
//ZoneScoped;
(work.thunk)(work.raw.data());
}
catch (...)
{
// can't do anything
}
(work.deleter)(work.raw.data());
if (work.pseudosema)
{
work.pseudosema->fetch_sub(1, std::memory_order_relaxed);
}
}
static void pool_executor(
//int thread_index,
std::shared_ptr<std::atomic<bool>> pool_alive,
std::shared_ptr<std::mutex> worker_ready_mutex,
std::shared_ptr<std::condition_variable> worker_ready_condvar,
std::shared_ptr<ThreadPool::Queue> my_wq,
std::vector<std::shared_ptr<ThreadPool::Queue>> other_wqs
)
{
{
//std::string thread_name = fmt::format("Thread Pool Thread {}", thread_index);
//tracy::SetThreadName(thread_name.c_str());
}
int spins = 0;
while (true)
{
std::optional<ThreadPool::Task> work = my_wq->steal();
bool did_work = false;
if (work)
{
do_work(*work);
did_work = true;
spins = 0;
}
else
{
for (auto& q : other_wqs)
{
work = q->steal();
if (work)
{
do_work(*work);
did_work = true;
spins = 0;
// We only want to steal one work item at a time, to prioritize our own queue
break;
}
}
}
if (!did_work)
{
// Spin a few loops to avoid yielding, then wait for the ready lock
spins += 1;
if (spins > 100)
{
std::unique_lock<std::mutex> ready_lock {*worker_ready_mutex};
while (my_wq->empty() && pool_alive->load())
{
worker_ready_condvar->wait(ready_lock);
}
if (!pool_alive->load())
{
break;
}
}
}
}
}
ThreadPool::ThreadPool()
{
immediate_mode_ = true;
}
ThreadPool::ThreadPool(size_t threads)
{
next_queue_index_ = 0;
pool_alive_ = std::make_shared<std::atomic<bool>>(true);
for (size_t i = 0; i < threads; i++)
{
std::shared_ptr<Queue> wsq = std::make_shared<Queue>(2048);
work_queues_.push_back(wsq);
std::shared_ptr<std::mutex> mutex = std::make_shared<std::mutex>();
worker_ready_mutexes_.push_back(std::move(mutex));
std::shared_ptr<std::condition_variable> condvar = std::make_shared<std::condition_variable>();
worker_ready_condvars_.push_back(std::move(condvar));
}
for (size_t i = 0; i < threads; i++)
{
std::shared_ptr<Queue> my_queue = work_queues_[i];
std::vector<std::shared_ptr<Queue>> other_queues;
for (size_t j = 0; j < threads; j++)
{
// Order the other queues starting from the next adjacent worker
// i.e. if this is worker 2 of 8, then other queues is 3, 4, 5, 6, 7, 0, 1
// This tries to balance out work stealing behavior
size_t other_index = j + i;
if (other_index >= threads)
{
other_index -= threads;
}
if (other_index != i)
{
other_queues.push_back(work_queues_[other_index]);
}
}
std::thread thread;
try
{
thread = std::thread
{
pool_executor,
//i,
pool_alive_,
worker_ready_mutexes_[i],
worker_ready_condvars_[i],
my_queue,
other_queues
};
}
catch (const std::system_error& error)
{
// Safe shutdown and rethrow
pool_alive_->store(false);
for (auto& t : threads_)
{
t.join();
}
throw error;
}
threads_.push_back(std::move(thread));
}
}
ThreadPool::ThreadPool(ThreadPool&&) = default;
ThreadPool::~ThreadPool() = default;
ThreadPool& ThreadPool::operator=(ThreadPool&&) = default;
void ThreadPool::begin_sema()
{
sema_begun_ = true;
}
ThreadPool::Sema ThreadPool::end_sema()
{
Sema ret = Sema(std::move(cur_sema_));
cur_sema_ = nullptr;
sema_begun_ = false;
return ret;
}
void ThreadPool::notify()
{
for (size_t i = 0; i < work_queues_.size(); i++)
{
auto& q = work_queues_[i];
size_t count = q->size();
if (count > 0)
{
worker_ready_condvars_[i]->notify_one();
}
}
}
void ThreadPool::notify_sema(const ThreadPool::Sema& sema)
{
if (!sema.pseudosema_)
{
return;
}
notify();
}
void ThreadPool::wait_idle()
{
if (immediate_mode_)
{
return;
}
//ZoneScoped;
for (size_t i = 0; i < work_queues_.size(); i++)
{
auto& q = work_queues_[i];
std::optional<Task> work;
while ((work = q->pop()).has_value())
{
do_work(*work);
}
}
}
void ThreadPool::wait_sema(const Sema& sema)
{
if (!sema.pseudosema_)
{
return;
}
//ZoneScoped;
while (sema.pseudosema_->load(std::memory_order_seq_cst) > 0)
{
// spin to win
for (size_t i = 0; i < work_queues_.size(); i++)
{
auto& q = work_queues_[i];
std::optional<Task> work;
if ((work = q->pop()).has_value())
{
do_work(*work);
break;
}
}
}
if (sema.pseudosema_->load(std::memory_order_seq_cst) != 0)
{
throw std::exception();
}
}
void ThreadPool::shutdown()
{
if (immediate_mode_)
{
return;
}
wait_idle();
pool_alive_->store(false);
for (auto& condvar : worker_ready_condvars_)
{
condvar->notify_all();
}
for (auto& t : threads_)
{
t.join();
}
}
std::unique_ptr<ThreadPool> srb2::g_main_threadpool;
void I_ThreadPoolInit(void)
{
SRB2_ASSERT(g_main_threadpool == nullptr);
size_t thread_count = std::min(static_cast<unsigned int>(9), std::thread::hardware_concurrency());
if (thread_count > 1)
{
// The main thread will act as a worker when waiting for pool idle
// Make one less worker thread to avoid unnecessary context switching
thread_count -= 1;
}
if (M_CheckParm("-singlethreaded"))
{
g_main_threadpool = std::make_unique<ThreadPool>();
}
else
{
g_main_threadpool = std::make_unique<ThreadPool>(thread_count);
}
}
void I_ThreadPoolShutdown(void)
{
if (!g_main_threadpool)
{
return;
}
g_main_threadpool->shutdown();
g_main_threadpool = nullptr;
}
void I_ThreadPoolSubmit(srb2cthunk_t thunk, void* data)
{
SRB2_ASSERT(g_main_threadpool != nullptr);
g_main_threadpool->schedule([=]() {
(thunk)(data);
});
g_main_threadpool->notify();
}
void I_ThreadPoolWaitIdle(void)
{
SRB2_ASSERT(g_main_threadpool != nullptr);
g_main_threadpool->wait_idle();
}
+163
View File
@@ -0,0 +1,163 @@
// BLANKART
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
// Copyright (C) 2024 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
#ifndef __SRB2_CORE_THREAD_POOL_H__
#define __SRB2_CORE_THREAD_POOL_H__
#include <stddef.h>
#ifdef __cplusplus
#include <condition_variable>
#include <cstddef>
#include <functional>
#include <memory>
#include <mutex>
#include <thread>
#include <utility>
#include <vector>
#include "spmc_queue.hpp"
namespace srb2
{
class ThreadPool
{
public:
struct Task
{
void (*thunk)(void*);
void (*deleter)(void*);
std::shared_ptr<std::atomic<uint32_t>> pseudosema;
std::array<std::byte, 512 - sizeof(void(*)(void*)) * 2 - sizeof(std::shared_ptr<std::atomic<uint32_t>>)> raw;
};
using Queue = SpMcQueue<Task>;
class Sema
{
std::shared_ptr<std::atomic<uint32_t>> pseudosema_;
explicit Sema(std::shared_ptr<std::atomic<uint32_t>> sema) : pseudosema_(sema) {}
friend class ThreadPool;
public:
Sema() = default;
};
private:
std::shared_ptr<std::atomic<bool>> pool_alive_;
std::vector<std::shared_ptr<std::mutex>> worker_ready_mutexes_;
std::vector<std::shared_ptr<std::condition_variable>> worker_ready_condvars_;
std::vector<std::shared_ptr<Queue>> work_queues_;
std::vector<std::thread> threads_;
size_t next_queue_index_ = 0;
std::shared_ptr<std::atomic<uint32_t>> cur_sema_;
bool immediate_mode_ = false;
bool sema_begun_ = false;
public:
ThreadPool();
explicit ThreadPool(size_t threads);
ThreadPool(const ThreadPool&) = delete;
ThreadPool(ThreadPool&&);
~ThreadPool();
ThreadPool& operator=(const ThreadPool&) = delete;
ThreadPool& operator=(ThreadPool&&);
void begin_sema();
ThreadPool::Sema end_sema();
/// Enqueue but don't notify
template <typename T> void schedule(T&& thunk);
/// Notify threads after several schedules
void notify();
void notify_sema(const Sema& sema);
void wait_idle();
void wait_sema(const Sema& sema);
void shutdown();
};
extern std::unique_ptr<ThreadPool> g_main_threadpool;
template <typename F>
void callable_caller(F* f)
{
(*f)();
}
template <typename F>
void callable_destroyer(F* f)
{
f->~F();
}
template <typename T>
void ThreadPool::schedule(T&& thunk)
{
static_assert(sizeof(T) <= sizeof(std::declval<Task>().raw));
if (immediate_mode_)
{
(thunk)();
return;
}
if (sema_begun_)
{
if (cur_sema_ == nullptr)
{
cur_sema_ = std::make_shared<std::atomic<uint32_t>>(0);
}
cur_sema_->fetch_add(1, std::memory_order_relaxed);
}
size_t qi = next_queue_index_;
{
std::shared_ptr<Queue> q = work_queues_[qi];
Task task;
task.thunk = reinterpret_cast<void(*)(void*)>(callable_caller<T>);
task.deleter = reinterpret_cast<void(*)(void*)>(callable_destroyer<T>);
task.pseudosema = cur_sema_;
new (reinterpret_cast<T*>(task.raw.data())) T(std::move(thunk));
q->push(std::move(task));
}
// worker_ready_condvars_[qi]->notify_one();
next_queue_index_ += 1;
if (next_queue_index_ >= threads_.size())
{
next_queue_index_ = 0;
}
}
} // namespace srb2
extern "C" {
#endif // __cplusplus
typedef void (*srb2cthunk_t)(void*);
void I_ThreadPoolInit(void);
void I_ThreadPoolShutdown(void);
void I_ThreadPoolSubmit(srb2cthunk_t thunk, void* data);
void I_ThreadPoolWaitIdle(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __SRB2_CORE_THREAD_POOL_H__
+152
View File
@@ -0,0 +1,152 @@
#ifndef __SRB2_CXXUTIL_HPP__
#define __SRB2_CXXUTIL_HPP__
#include <cstdlib>
#include <type_traits>
#include <utility>
#include "doomdef.h"
namespace srb2 {
template <class F>
class Finally {
public:
explicit Finally(const F& f) noexcept : f_(f) {}
explicit Finally(F&& f) noexcept : f_(f) {}
Finally(Finally&& from) noexcept : f_(std::move(from.f_)), call_(std::exchange(from.call_, false)) {}
Finally(const Finally& from) = delete;
void operator=(const Finally& from) = delete;
void operator=(Finally&& from) = delete;
~Finally() noexcept {
if (call_)
f_();
}
private:
F f_;
bool call_ = true;
};
template <class F>
Finally<std::decay_t<F>> finally(F&& f) noexcept {
return Finally {std::forward<F>(f)};
}
struct SourceLocation {
const char* file_name;
unsigned int line_number;
};
#define SRB2_SOURCE_LOCATION \
srb2::SourceLocation { __FILE__, __LINE__ }
#ifndef SRB2_ASSERT_HANDLER
#define SRB2_ASSERT_HANDLER srb2::IErrorAssertHandler
#endif
#if !defined(NDEBUG) || defined(PARANOIA)
// An assertion level of 2 will activate all invocations of the SRB2_ASSERT macro
#define SRB2_ASSERTION_LEVEL 2
#else
// The minimum assertion level is 1
#define SRB2_ASSERTION_LEVEL 1
#endif
/// Assert a precondition expression in debug builds.
#define SRB2_ASSERT(expr) srb2::do_assert<2, SRB2_ASSERT_HANDLER>([&] { return (expr); }, SRB2_SOURCE_LOCATION, #expr)
class IErrorAssertHandler {
public:
static void handle(const SourceLocation& source_location, const char* expression) {
I_Error("Assertion failed at %s:%u: %s != true",
source_location.file_name,
source_location.line_number,
expression);
}
};
class NoOpAssertHandler {
public:
static void handle(const SourceLocation& source_location, const char* expression) {(void)source_location; (void)expression;}
};
/// @brief Assert a precondition expression, aborting the application if it fails.
/// @tparam Expr
/// @tparam Level the level of this assertion; if it is less than or equal to SRB2_ASSERTION_LEVEL, this overload will
/// activate.
/// @param expr a callable which returns a bool
/// @param source_location a struct containing the source location of the assertion, e.g. SRB2_SOURCE_LOCATION
/// @param expression the expression evaluated in the expression callable
/// @param message an optional message to display for the assertion
template <unsigned int Level, class Handler, class Expr>
std::enable_if_t<(Level <= SRB2_ASSERTION_LEVEL), void>
do_assert(const Expr& expr, const SourceLocation& source_location, const char* expression = "") noexcept {
static_assert(Level > 0, "level of an assertion must not be 0");
if (!expr()) {
Handler::handle(source_location, expression);
std::abort();
}
}
template <unsigned int Level, class, class Expr>
std::enable_if_t<(Level > SRB2_ASSERTION_LEVEL), void>
do_assert(const Expr&, const SourceLocation&, const char* = "") noexcept {
}
template <typename T>
class NotNull final {
T ptr_;
public:
static_assert(std::is_convertible_v<decltype(std::declval<T>() != nullptr), bool>,
"T is not comparable with nullptr_t");
/// @brief Move-construct from the pointer value U, asserting that it is not null. Allows construction of a
/// NotNull<T> from any compatible pointer U, for example with polymorphic classes.
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
constexpr NotNull(U&& rhs) : ptr_(std::forward<U>(rhs)) {
SRB2_ASSERT(ptr_ != nullptr);
}
/// @brief Wrap the pointer type T, asserting that the pointer is not null.
template <typename = std::enable_if_t<!std::is_same_v<std::nullptr_t, T>>>
constexpr NotNull(T rhs) : ptr_(std::move(rhs)) {
SRB2_ASSERT(ptr_ != nullptr);
}
/// @brief Copy construction from NotNull of convertible type U. Only if the incoming pointer is NotNull already.
template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, T>>>
constexpr NotNull(const NotNull<U>& rhs) : NotNull(rhs.get()) {
// Value is guaranteed to be not null by construction; no assertion necessary
}
NotNull(const NotNull& rhs) = default;
NotNull& operator=(const NotNull& rhs) = default;
/// @brief Get the stored pointer.
constexpr T get() const { return ptr_; }
/// @brief Convert to T (the pointer type).
constexpr operator T() const { return get(); }
/// @brief Arrow-dereference to *T (the actual value pointed to).
constexpr decltype(auto) operator->() const { return get(); }
/// @brief Dereference to *T (the actual value pointed to).
constexpr decltype(auto) operator*() const { return *get(); }
// It is not allowed to construct NotNull<T> with nullptr regardless of T.
NotNull(std::nullptr_t) = delete;
NotNull& operator=(std::nullptr_t) = delete;
};
template <class T>
NotNull(T) -> NotNull<T>;
} // namespace srb2
#endif // __SRB2_CXXUTIL_HPP__
+158 -35
View File
@@ -87,6 +87,9 @@ boolean serverrunning = false;
INT32 serverplayer = 0;
char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support)
plrinfo playerinfo[MAXPLAYERS];
SINT8 joinnode = 0; // used for CL_VIEWSERVER
// Server specific vars
UINT8 playernode[MAXPLAYERS];
@@ -95,7 +98,7 @@ UINT8 playernode[MAXPLAYERS];
tic_t jointimeout = (3*TICRATE);
static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame?
#ifdef SATURNPAK
static boolean resendingsavegame[MAXNETNODES]; // Are we resending the savegame?
static tic_t resendingsavegame[MAXNETNODES]; // Are we resending the savegame?
static tic_t savegameresendcooldown[MAXNETNODES]; // How long before we can resend again?
#endif
static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout?
@@ -1068,6 +1071,7 @@ static void SV_RequireResynch(INT32 node)
// Initial setup
memset(resynch_sent[node], 0, MAXPLAYERS);
for (i = 0; i < MAXPLAYERS; ++i)
{
if (!playeringame[i]) // Player not in game so just drop it from required synch
@@ -1184,6 +1188,7 @@ typedef enum
#endif
CL_CONNECTED,
CL_ABORTED,
CL_VIEWSERVER,
CL_ASKFULLFILELIST,
CL_CONFIRMCONNECT,
#ifdef HAVE_CURL
@@ -1247,7 +1252,7 @@ static inline void CL_DrawConnectionStatus(void)
if (!menuactive) // menu already draws its own fade
V_DrawFadeScreen(0xFF00, 16); // force default
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES && cl_mode != CL_CHECKFILES
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES && cl_mode != CL_CHECKFILES && cl_mode != CL_VIEWSERVER
#ifdef HAVE_CURL
&& cl_mode != CL_DOWNLOADHTTPFILES
#endif
@@ -1367,6 +1372,78 @@ static inline void CL_DrawConnectionStatus(void)
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE|MENUCAPS,
va(" %2u/%2u Files",loadcompletednum,fileneedednum));
}
else if (cl_mode == CL_VIEWSERVER)
{
V_DrawFill(8, 16, BASEVIDWIDTH - 16, 54, 239);
V_DrawThinString(12 + 80, 18, V_ALLOWLOWERCASE, va("%s", serverlist[joinnode].info.servername));
const char *map = va("%sP", serverlist[joinnode].info.mapname);
patch_t *current_map = W_LumpExists(map) ? W_CachePatchName(map, PU_CACHE) : W_CachePatchName("BLANKLVL", PU_CACHE);
V_DrawSmallScaledPatch(10, 18, 0, current_map);
V_DrawThinString(12 + 80, 38, V_ALLOWLOWERCASE, va("%s", serverlist[joinnode].info.maptitle));
V_DrawThinString(12 + 80, 48, V_ALLOWLOWERCASE, va("%s", Gametype_Names[serverlist[joinnode].info.gametype]));
if (fileneedednum > 0)
{
V_DrawThinString(12 + 80, 58, V_ALLOWLOWERCASE|V_ORANGEMAP, va("%i Addons", fileneedednum));
}
else
{
V_DrawThinString(12 + 80, 58, V_ALLOWLOWERCASE|V_YELLOWMAP, "Vanilla");
}
if (serverlist[joinnode].info.cheatsenabled)
{
V_DrawRightAlignedThinString(BASEVIDWIDTH - 12, 58, V_ALLOWLOWERCASE|V_GREENMAP, "Cheats");
}
V_DrawFill(8, 72, BASEVIDWIDTH - 16, 112, 239);
V_DrawString(12, 74, V_ALLOWLOWERCASE|V_YELLOWMAP, "Players");
V_DrawRightAlignedString(BASEVIDWIDTH - 12, 74, V_ALLOWLOWERCASE|V_YELLOWMAP, va("%i / %i", serverlist[joinnode].info.numberofplayer, serverlist[joinnode].info.maxplayer));
INT32 i;
INT32 count = 0;
INT32 x = 14;
INT32 y = 84;
INT32 statuscolor = 1;
char player_name[MAXPLAYERNAME+1];
if (serverlist[joinnode].info.numberofplayer > 0)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (playerinfo[i].node < 255)
{
strncpy(player_name, playerinfo[i].name, MAXPLAYERNAME);
V_DrawThinString(x + 10, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE, player_name);
if (playerinfo[i].team == 0) { statuscolor = 184; } // playing
if (playerinfo[i].data & 0x20) { statuscolor = 86; } // tag IT
if (playerinfo[i].team == 1) { statuscolor = 128; } // ctf red team
if (playerinfo[i].team == 2) { statuscolor = 232; } // ctf blue team
if (playerinfo[i].team == 255) { statuscolor = 16; } // spectator or non-team
V_DrawFill(x, y, 7, 7, 31);
V_DrawFill(x, y, 6, 6, statuscolor);
y += 9;
count++;
if ((count == 11) || (count == 22))
{
x += 104;
y = 84;
}
}
}
}
// Buttons
V_DrawFill(8, BASEVIDHEIGHT - 14, BASEVIDWIDTH - 16, 12, 239);
V_DrawThinString(16, BASEVIDHEIGHT - 12, V_ALLOWLOWERCASE, va("[%sESC%s] = Abort", "\x82", "\x80"));
V_DrawRightAlignedThinString(BASEVIDWIDTH - 12, BASEVIDHEIGHT - 12, V_ALLOWLOWERCASE, va("[%sENTER%s] = Join", "\x82", "\x80"));
}
else if (filedownload.current != -1)
{
INT32 dldlength;
@@ -1687,13 +1764,7 @@ static void SV_SendPlayerInfo(INT32 node)
for (i = 0; i < MSCOMPAT_MAXPLAYERS; i++)
{
if (i >= MAXPLAYERS)
{
netbuffer->u.playerinfo[i].node = 255;
continue;
}
if (playeringame[i] == UINT8_MAX || !playeringame[i])
if ((i >= MAXPLAYERS) || !playeringame[i])
{
netbuffer->u.playerinfo[i].node = 255; // This slot is empty.
continue;
@@ -1778,8 +1849,6 @@ static boolean SV_SendServerConfig(INT32 node)
memset(netbuffer->u.servercfg.playerskins, 0xFF, sizeof(netbuffer->u.servercfg.playerskins));
memset(netbuffer->u.servercfg.playercolor, 0xFF, sizeof(netbuffer->u.servercfg.playercolor));
memset(netbuffer->u.servercfg.adminplayers, -1, sizeof(netbuffer->u.servercfg.adminplayers));
for (i = 0; i < MAXPLAYERS; i++)
{
netbuffer->u.servercfg.adminplayers[i] = (SINT8)adminplayers[i];
@@ -2476,6 +2545,7 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
if (i < 0)
return true;
}
joinnode = i;
// Quit here rather than downloading files and being refused later.
if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer)
@@ -2502,7 +2572,7 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
return true;
}
cl_mode = CL_CHECKFILES;
cl_mode = (cv_serverinfoscreen.value) ? CL_VIEWSERVER : CL_CHECKFILES;
}
else
{
@@ -2556,7 +2626,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
case CL_ASKFULLFILELIST:
if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved
cl_mode = CL_CHECKFILES;
cl_mode = (cv_serverinfoscreen.value) ? CL_VIEWSERVER : CL_CHECKFILES;
else if (fileneedednum != cl_lastcheckedfilecount || I_GetTime() >= *asksent)
{
if (CL_AskFileList(fileneedednum))
@@ -2722,6 +2792,15 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
D_ProcessEvents(); //needed for menu system to receive inputs
key = I_GetKey();
if (cl_mode == CL_VIEWSERVER)
{
if (key == KEY_ENTER || key == KEY_JOY1)
cl_mode = CL_CHECKFILES;
else if (key == KEY_ESCAPE || key == KEY_JOY1+1)
cl_mode = CL_ABORTED;
}
// Only ESC and non-keyboard keys abort connection
if (!modeattacking && (key == KEY_ESCAPE || key == KEY_JOY1+1 || cl_mode == CL_ABORTED))
{
@@ -3275,7 +3354,7 @@ void CL_ClearPlayer(INT32 playernum)
P_RemoveMobj(players[playernum].mo);
}
memset(&players[playernum], 0, sizeof (player_t));
memset(&players[playernum], 0, sizeof(player_t));
}
//
@@ -4149,6 +4228,8 @@ consvar_t cv_downloadspeed = {"downloadspeed", "300", CV_SAVE, downloadspeed_con
static CV_PossibleValue_t connectawaittime_cons_t[] = {{1, "MIN"}, {60, "MAX"}, {0, "Inf"}, {0, NULL}};
consvar_t cv_connectawaittime = {"connectawaittime", "5", CV_SAVE, connectawaittime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_serverinfoscreen = {"serverinfoscreen", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static void Got_AddPlayer(UINT8 **p, INT32 playernum);
static void Got_RemovePlayer(UINT8 **p, INT32 playernum);
@@ -4251,7 +4332,7 @@ static void ResetNode(INT32 node)
// SATURN
#ifdef SATURNPAK
is_client_saturn[node] = false;
resendingsavegame[node] = false;
resendingsavegame[node] = 0;
savegameresendcooldown[node] = 0;
gamestate_resend_counter[node] = 0;
#endif
@@ -4284,14 +4365,14 @@ void SV_ResetServer(void)
sprintf(player_names[i], "Player %d", i + 1);
}
memset(player_name_changes, 0, sizeof player_name_changes);
memset(player_name_changes, 0, sizeof(player_name_changes));
memset(playeringame, false, sizeof playeringame);
memset(playernode, UINT8_MAX, sizeof playernode);
memset(playeringame, false, sizeof(playeringame));
memset(playernode, UINT8_MAX, sizeof(playernode));
pingmeasurecount = 1;
memset(realpingtable, 0, sizeof realpingtable);
memset(playerpingtable, 0, sizeof playerpingtable);
memset(realpingtable, 0, sizeof(realpingtable));
memset(playerpingtable, 0, sizeof(playerpingtable));
ClearAdminPlayers();
@@ -4916,6 +4997,16 @@ static void HandleServerInfo(SINT8 node)
if (client && cl_mode > CL_SEARCHING && node == servernode)
memcpy(connectedservername, netbuffer->u.serverinfo.servername, MAXSERVERNAME);
}
static void HandlePlayerInfo(SINT8 node)
{
(void)node;
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
playerinfo[i] = netbuffer->u.playerinfo[i];
}
#endif
#ifdef SATURNPAK
@@ -4952,7 +5043,7 @@ static void PT_CanReceiveGamestate(SINT8 node)
CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[nodetoplayer[node]]);
SV_SendSaveGame(node, true); // Resend a complete game state
resendingsavegame[node] = true;
resendingsavegame[node] = 1;
}
#endif
@@ -5204,6 +5295,10 @@ static void HandlePacketFromAwayNode(SINT8 node)
case PT_CLIENTCMD:
break; // This is not an "unknown packet"
case PT_PLAYERINFO:
HandlePlayerInfo(node);
break;
case PT_SERVERTICS:
// Do not remove my own server (we have just get a out of order packet)
@@ -5324,18 +5419,18 @@ static void HandlePacketFromPlayer(SINT8 node)
/// \todo Use a separate cvar for that kind of timeout?
freezetimeout[node] = I_GetTime() + connectiontimeout;
// If we've alredy received a ticcmd for this tic, just submit it for the next one.
tic_t faketic = maketic;
if ((!!(netcmds[maketic % TICQUEUE][netconsole].angleturn & TICCMD_RECEIVED))
&& (maketic - firstticstosend < TICQUEUE - 1))
faketic++;
// Don't do anything for packets of type NODEKEEPALIVE?
// Sryder 2018/07/01: Update the freezetimeout still!
if (netbuffer->packettype == PT_NODEKEEPALIVE
|| netbuffer->packettype == PT_NODEKEEPALIVEMIS)
break;
// If we've alredy received a ticcmd for this tic, just submit it for the next one.
tic_t faketic = maketic;
if ((!!(netcmds[maketic % TICQUEUE][netconsole].angleturn & TICCMD_RECEIVED))
&& (maketic - firstticstosend < TICQUEUE - 1))
faketic++;
// Copy ticcmd
G_MoveTiccmd(&netcmds[faketic%TICQUEUE][netconsole], &netbuffer->u.clientpak.cmd, 1);
@@ -5395,11 +5490,11 @@ static void HandlePacketFromPlayer(SINT8 node)
// Check player consistancy during the level
if (gamestate == GS_LEVEL
&& (realstart > gametic - TICQUEUE+1 && realstart <= gametic)
&& (realstart <= gametic && realstart + TICQUEUE - 1 > gametic)
&& consistancy[realstart%TICQUEUE] != SHORT(netbuffer->u.clientpak.consistancy)
&& (!UseSaturnSynch(node) || (!resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime() && !SV_ResendingSavegameToAnyone())))
{
resendingsavegame[node] = false; // reset this before just in case
resendingsavegame[node] = 0; // reset this before just in case
// Check if a client is saturn before sending ANYTHING!
// this way we only send stuff to clients we know can use the gamestate resend
@@ -5409,7 +5504,7 @@ static void HandlePacketFromPlayer(SINT8 node)
// Tell the client we are about to resend them the gamestate
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
HSendPacket(node, true, 0, 0);
resendingsavegame[node] = true;
resendingsavegame[node] = 1;
}
else if (UseVanillaSynch(node))
{
@@ -5425,10 +5520,13 @@ static void HandlePacketFromPlayer(SINT8 node)
}
if (cv_blamecfail.value)
{
CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"),
netconsole+1, player_names[netconsole],
consistancy[realstart%TICQUEUE],
SHORT(netbuffer->u.clientpak.consistancy));
}
DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n",
netconsole, realstart, consistancy[realstart%TICQUEUE],
SHORT(netbuffer->u.clientpak.consistancy)));
@@ -5700,7 +5798,7 @@ static void HandlePacketFromPlayer(SINT8 node)
break;
}
//Update client ping table from the server.
// Update client ping table from the server.
if (client)
{
UINT8 i;
@@ -5736,7 +5834,7 @@ static void HandlePacketFromPlayer(SINT8 node)
break;
case PT_RECEIVEDGAMESTATE:
sendingsavegame[node] = false;
resendingsavegame[node] = false;
resendingsavegame[node] = 0;
savegameresendcooldown[node] = I_GetTime() + cv_resynchcooldown.value * TICRATE; // I_GetTime() + 5 * TICRATE;
break;
case PT_WILLRESENDGAMESTATE:
@@ -5796,8 +5894,9 @@ static void GetPackets(void)
}
#endif
if (netbuffer->packettype == PT_PLAYERINFO)
continue; // We do nothing with PLAYERINFO, that's for the MS browser.
/*if (netbuffer->packettype == PT_PLAYERINFO)
continue; // We do nothing with PLAYERINFO, that's for the MS browser. Not quite true anymore :p*/
// We also count unknown packets, hence "<="
if (netbuffer->packettype <= NUMPACKETTYPE)
@@ -6366,10 +6465,35 @@ static void SV_Maketic(void)
maketic++;
}
#ifdef SATURNPAK
static void SV_UpdateResendGamestateTimeout(void)
{
for (INT32 i = 0; i < MAXNETNODES; ++i)
{
if (!resendingsavegame[i])
continue;
resendingsavegame[i]++;
// Resending savegame took too long
if (resendingsavegame[i] > (tic_t)TICRATE*cv_pingtimeout.value)
{
resendingsavegame[i] = 0;
SendKick(i, KICK_MSG_CON_FAIL);
}
}
}
#endif
boolean TryRunTics(tic_t realtics)
{
boolean ticking;
#ifdef SATURNPAK
if (server)
SV_UpdateResendGamestateTimeout();
#endif
// the machine has lagged but it is not so bad
if (realtics > TICRATE/7) // FIXME: consistency failure!!
{
@@ -6510,7 +6634,6 @@ static inline void PingUpdate(void)
if (pingtimeout[i] > 0)
pingtimeout[i]--;
}
}
//kick lagging players... unless everyone but the server's ping sucks.
+14
View File
@@ -13,6 +13,10 @@
#ifndef __D_CLISRV__
#define __D_CLISRV__
#ifdef __cplusplus
extern "C" {
#endif
#include "d_ticcmd.h"
#include "d_net.h"
#include "d_netcmd.h"
@@ -577,6 +581,9 @@ extern boolean acceptnewnode;
extern SINT8 servernode;
extern char connectedservername[MAXSERVERNAME+1];
extern plrinfo playerinfo[MAXPLAYERS];
extern SINT8 joinnode;
void Command_Ping_f(void);
extern tic_t connectiontimeout;
extern tic_t jointimeout;
@@ -608,6 +615,8 @@ extern consvar_t cv_connectawaittime;
extern consvar_t cv_discordinvites;
extern consvar_t cv_serverinfoscreen;
// Used in d_net, the only dependence
//tic_t ExpandTics(INT32 low, tic_t basetic);
void D_ClientServerInit(void);
@@ -689,4 +698,9 @@ typedef struct rewind_s {
void CL_ClearRewinds(void);
rewind_t *CL_SaveRewindPoint(size_t demopos);
rewind_t *CL_RewindToTime(tic_t time);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+154 -125
View File
@@ -73,6 +73,8 @@
#include "m_perfstats.h"
#include "k_kart.h"
#include "core/memory.h"
#include "lua_script.h"
#ifdef CMAKECONFIG
@@ -197,12 +199,10 @@ static void D_PadMenuScrollInput(UINT8 input)
// and pass it to the eventlist
static void D_GamePadMenuScrollTicker(void)
{
UINT8 i;
static UINT8 menuInputDelayTimer = 0;
if (dedicated)
return;
for (UINT8 i = 0; i < 4; i++)
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
if (dpadscrollstate[i])
{
@@ -222,10 +222,10 @@ static void D_GamePadMenuScrollTicker(void)
static void D_DeviceLEDTick(void)
{
UINT8 i;
static UINT16 color[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0};
static UINT16 color[MAXSPLITSCREENPLAYERS] = {0};
static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0};
if (dedicated || numcontrollers == 0)
if (numcontrollers == 0)
{
return;
}
@@ -252,7 +252,6 @@ static void D_DeviceLEDTick(void)
void D_ProcessEvents(void)
{
event_t *ev;
boolean eaten;
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
@@ -291,8 +290,10 @@ void D_ProcessEvents(void)
// Demo input:
if (demo.playback)
{
if (M_DemoResponder(ev))
continue; // demo ate the event
}
// console input
#ifdef HAVE_THREADS
@@ -317,6 +318,110 @@ void D_ProcessEvents(void)
// draw current display, possibly wiping it from the previous
//
static void D_Renderview(void)
{
UINT8 i;
if (automapactive)
return;
R_ApplyLevelInterpolators(rendertimefrac);
if (rendermode == render_soft)
{
// if this is display player 1
if (cv_homremoval.value)
{
if (cv_homremoval.value == 1)
{
// Clear the software screen buffer to remove HOM
memset(vid.screens[0], 31, vid.width * vid.height);
}
else if (cv_homremoval.value == 2)
{
//'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
memset(vid.screens[0], 32+(timeinmap&15), vid.width * vid.height);
}
}
}
// Draw over the fourth screen so you don't have to stare at a HOM :V
if (splitscreen == 2)
{
// V_DrawPatchFill, but for the fourth screen only
patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE);
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz;
for (x = vid.width>>1; x < vid.width; x += pw)
{
for (y = vid.height>>1; y < vid.height; y += ph)
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
}
}
for (i = 0; i <= splitscreen; i++)
{
const boolean issplitscreen = (i > 0);
if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD)
{
viewssnum = i;
if (!issplitscreen) // Initialize for P1
{
viewwindowy = viewwindowx = 0;
objectsdrawn = 0;
}
#ifdef HWRENDER
if (rendermode == render_opengl)
{
HWR_RenderPlayerView();
R_RestoreLevelInterpolators();
continue;
}
#endif
if (issplitscreen) // Splitscreen-specific
{
switch (i)
{
case 1:
if (splitscreen > 1)
{
viewwindowx = viewwidth;
viewwindowy = 0;
}
else
{
viewwindowx = 0;
viewwindowy = viewheight;
}
break;
case 2:
viewwindowx = 0;
viewwindowy = viewheight;
break;
case 3:
viewwindowx = viewwidth;
viewwindowy = viewheight;
default:
break;
}
}
R_RenderPlayerView(&players[displayplayers[i]]);
}
if (!issplitscreen)
R_ApplyViewMorph();
V_DoPostProcessor(i, postimgparam[i]);
}
R_RestoreLevelInterpolators();
}
// wipegamestate can be set to -1 to force a wipe on the next draw
// added comment : there is a wipe eatch change of the gamestate
gamestate_t wipegamestate = GS_LEVEL;
@@ -327,7 +432,6 @@ static boolean D_Display(void)
boolean forcerefresh = false;
static boolean wipe = false;
INT32 wipedefindex = 0;
UINT8 i;
if (!dedicated)
{
@@ -366,6 +470,7 @@ static boolean D_Display(void)
{
// set for all later
wipedefindex = gamestate; // wipe_xxx_toblack
if (gamestate == GS_TITLESCREEN && wipegamestate != GS_INTRO)
wipedefindex = wipe_timeattack_toblack;
else if (gamestate == GS_INTERMISSION)
@@ -378,26 +483,28 @@ static boolean D_Display(void)
if (!dedicated)
{
// Fade to black first
if (gamestate != GS_LEVEL // fades to black on its own timing, always
&& wipedefs[wipedefindex] != UINT8_MAX)
if (gamestate != GS_LEVEL)
{
F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
F_WipeEndScreen();
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
ranwipe = true;
}
// Fade to black first
if (wipedefs[wipedefindex] != UINT8_MAX) // fades to black on its own timing, always
{
F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
F_WipeEndScreen();
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
ranwipe = true;
}
if (gamestate != GS_LEVEL && rendermode != render_none)
{
V_SetPaletteLump("PLAYPAL"); // Reset the palette
R_ReInitColormaps(0, LUMPERROR);
if (rendermode != render_none)
{
V_SetPaletteLump("PLAYPAL"); // Reset the palette
R_ReInitColormaps(0, LUMPERROR);
}
}
F_WipeStartScreen();
}
else //dedicated servers
else // dedicated servers
{
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
ranwipe = true;
@@ -405,7 +512,7 @@ static boolean D_Display(void)
}
}
if (dedicated) //bail out after wipe logic
if (dedicated) // bail out after wipe logic
return false;
// do buffered drawing
@@ -430,9 +537,6 @@ static boolean D_Display(void)
HU_Drawer();
break;
case GS_TIMEATTACK:
break;
case GS_INTRO:
F_IntroDrawer();
if (wipegamestate == (gamestate_t)-1)
@@ -484,6 +588,7 @@ static boolean D_Display(void)
HU_Erase();
HU_Drawer();
}
case GS_TIMEATTACK:
case GS_DEDICATEDSERVER:
case GS_NULL:
break;
@@ -492,89 +597,10 @@ static boolean D_Display(void)
if (gamestate == GS_LEVEL)
{
// draw the view directly
if (cv_renderview.value && !automapactive)
if (cv_renderview.value)
{
PS_START_TIMING(ps_rendercalltime);
R_ApplyLevelInterpolators(rendertimefrac);
for (i = 0; i <= splitscreen; i++)
{
if (!P_MobjWasRemoved(players[displayplayers[i]].mo) || players[displayplayers[i]].playerstate == PST_DEAD)
{
viewssnum = i;
if (i == 0) // Initialize for P1
{
viewwindowy = 0;
viewwindowx = 0;
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
objectsdrawn = 0;
}
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_RenderPlayerView();
else
#endif
if (rendermode != render_none)
{
if (i > 0) // Splitscreen-specific
{
switch (i)
{
case 1:
if (splitscreen > 1)
{
viewwindowx = viewwidth;
viewwindowy = 0;
}
else
{
viewwindowx = 0;
viewwindowy = viewheight;
}
M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0]));
break;
case 2:
viewwindowx = 0;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup3, viewheight*sizeof (ylookup[0]));
break;
case 3:
viewwindowx = viewwidth;
viewwindowy = viewheight;
M_Memcpy(ylookup, ylookup4, viewheight*sizeof (ylookup[0]));
default:
break;
}
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
}
R_RenderPlayerView(&players[displayplayers[i]]);
if (i > 0)
M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0]));
}
}
}
if (rendermode == render_soft)
{
if (!splitscreen)
R_ApplyViewMorph();
for (i = 0; i <= splitscreen; i++)
{
V_DoPostProcessor(i, postimgparam[i]);
}
}
R_RestoreLevelInterpolators();
D_Renderview();
PS_STOP_TIMING(ps_rendercalltime);
}
@@ -582,8 +608,9 @@ static boolean D_Display(void)
{
if (rendermode == render_soft)
{
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
VID_BlitLinearScreen(vid.screens[0], vid.screens[1], vid.width, vid.height, vid.width, vid.rowbytes);
}
lastdraw = false;
}
@@ -606,13 +633,8 @@ static boolean D_Display(void)
// draw pause pic
if (paused && cv_showhud.value && !demo.playback)
{
INT32 py;
patch_t *patch;
if (automapactive)
py = 4;
else
py = viewwindowy + 4;
patch = W_CachePatchName("M_PAUSE", PU_PATCH);
INT32 py = (automapactive) ? 4 : (viewwindowy + 4);
patch_t *patch = W_CachePatchName("M_PAUSE", PU_PATCH);
V_DrawScaledPatch(viewwindowx + (BASEVIDWIDTH - patch->width)/2, py, V_SNAPTOTOP, patch);
}
@@ -620,7 +642,7 @@ static boolean D_Display(void)
V_DrawFadeScreen(TC_RAINBOW, (leveltime & 0x20) ? SKINCOLOR_PASTEL : SKINCOLOR_MOONSLAM);
// vid size change is now finished if it was on...
vid.recalc = 0;
vid.recalc = false;
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
@@ -752,9 +774,11 @@ void D_SRB2Loop(void)
precise_t enterprecise = I_GetPreciseTime();
precise_t finishprecise = enterprecise;
Z_Frame_Reset();
// Casting the return value of a function is bad practice (apparently)
double budget = ((R_GetFramerateCap() == 0) ? 0.0 : round((1.0 / R_GetFramerateCap()) * I_GetPrecisePrecision()));
capbudget = (precise_t) budget;
capbudget = (precise_t)budget;
boolean ranwipe = false;
@@ -824,12 +848,15 @@ void D_SRB2Loop(void)
doDisplay = true;
}
if (menuactive)
if (!dedicated)
{
D_GamePadMenuScrollTicker();
}
if (menuactive)
{
D_GamePadMenuScrollTicker();
}
D_DeviceLEDTick();
D_DeviceLEDTick();
}
}
if (interp)
@@ -841,7 +868,9 @@ void D_SRB2Loop(void)
ps_interp_frac.value.p = (precise_t)((FIXED_TO_FLOAT(g_time.timefrac)) * 1000.0f);
ps_interp_lag.value.p = (precise_t)((deltasecs) * 1000.0f);
if (!(paused || P_AutoPause()) && deltatics < 1.0 && !hu_stopped)
const boolean lagging = ((deltatics >= 1.0) || hu_stopped);
if (!(paused || P_AutoPause()) && !lagging)
{
rendertimefrac = g_time.timefrac;
}
@@ -850,7 +879,7 @@ void D_SRB2Loop(void)
rendertimefrac = FRACUNIT;
}
if ((deltatics < 1.0) && !hu_stopped)
if (!lagging)
{
rendertimefrac_unpaused = g_time.timefrac;
}
@@ -923,7 +952,7 @@ void D_SRB2Loop(void)
if ((elapsed > 0) && ((INT64)capbudget > elapsed) && !vsync_with_match_refresh)
{
I_SleepDuration(capbudget - (finishprecise - enterprecise));
I_SleepDuration(capbudget - elapsed);
}
}
// Capture the time once more to get the real delta time.
+8
View File
@@ -14,6 +14,10 @@
#ifndef __D_MAIN__
#define __D_MAIN__
#ifdef __cplusplus
extern "C" {
#endif
#include "d_event.h"
#include "w_wad.h" // for MAX_WADFILES
@@ -90,4 +94,8 @@ const char *D_Home(void);
//
void D_StartTitle(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__D_MAIN__
+8 -2
View File
@@ -18,6 +18,10 @@
#ifndef __D_NET__
#define __D_NET__
#ifdef __cplusplus
extern "C" {
#endif
// Max computers in a game
// 127 is probably as high as this can go, because
// SINT8 is used for nodes sometimes >:(
@@ -43,8 +47,6 @@ extern SINT8 nodetoplayer4[MAXNETNODES]; // Say the numplayer for this node if a
extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
extern boolean serverrunning;
void Net_AckTicker(void);
// If reliable return true if packet sent, 0 else
@@ -65,4 +67,8 @@ void Net_SendAcks(INT32 node);
void Net_WaitAllAckReceived(UINT32 timeout);
const char *Net_GetPacketName(UINT8 packettype);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+12 -12
View File
@@ -204,11 +204,6 @@ static void Command_Archivetest_f(void);
// CLIENT VARIABLES
// =========================================================================
void SendWeaponPref(void);
void SendWeaponPref2(void);
void SendWeaponPref3(void);
void SendWeaponPref4(void);
static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force"}, {0, NULL}};
static CV_PossibleValue_t autobalance_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NULL}};
@@ -216,11 +211,8 @@ static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2
static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
static CV_PossibleValue_t sleeping_cons_t[] = {{0, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}};
static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Teleports"},
{3, "None"}, {0, NULL}};
static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Non-Random"},
{3, "None"}, {0, NULL}};
static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Teleports"}, {3, "None"}, {0, NULL}};
static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Non-Random"}, {3, "None"}, {0, NULL}};
//static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}};
static CV_PossibleValue_t match_scoring_cons_t[] = {{0, "Normal"}, {1, "Classic"}, {0, NULL}};
@@ -903,6 +895,7 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_netticbuffer);
CV_RegisterVar(&cv_mindelay);
CV_RegisterVar(&cv_gentlemens);
CV_RegisterVar(&cv_serverinfoscreen);
#ifdef NETGAME_DEVMODE
CV_RegisterVar(&cv_fishcake);
@@ -1032,6 +1025,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_scr_width);
CV_RegisterVar(&cv_scr_height);
CV_RegisterVar(&cv_parallelsoftware);
CV_RegisterVar(&cv_soundtest);
CV_RegisterVar(&cv_perfstats);
@@ -2775,7 +2770,7 @@ static void Command_Map_f(void)
// G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer
else
{
if (!mapheaderinfo[newmapnum-1] || mapheaderinfo[newmapnum-1] == NULL)
if (!mapheaderinfo[newmapnum-1])
{
CONS_Alert(CONS_WARNING, M_GetText("Invalid mapheaderinfo for Course %s (%s)\n"), realmapname, G_BuildMapName(newmapnum));
Z_Free(realmapname);
@@ -3029,9 +3024,14 @@ static void Command_ReplayMarker(void)
adjustedleveltime = 0;
char *title = G_BuildMapTitle(gamemap);
snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
if (title)
{
snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
Z_Free(title);
}
else
snprintf(demo.titlename, 64, "[%i:%02d/%.5s]", G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
CONS_Printf("Replay will be saved!\n");
}
+13
View File
@@ -15,8 +15,17 @@
#ifndef __D_NETCMD__
#define __D_NETCMD__
#ifdef __cplusplus
extern "C" {
#endif
#include "command.h"
void SendWeaponPref(void);
void SendWeaponPref2(void);
void SendWeaponPref3(void);
void SendWeaponPref4(void);
// console vars
extern consvar_t cv_playername;
extern consvar_t cv_playercolor;
@@ -318,4 +327,8 @@ void D_SetPassword(const char *pw);
// used for the player setup menu
UINT8 CanChangeSkin(INT32 playernum);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+8
View File
@@ -111,7 +111,9 @@ static fileused_t transferFiles[UINT8_MAX + 1];
// Receiver structure
INT32 fileneedednum; // Number of files needed to join the server
fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
#ifdef HAVE_THREADS
static I_mutex downloadmutex;
#endif
char downloaddir[512] = "DOWNLOAD";
file_download_t filedownload;
@@ -1351,14 +1353,18 @@ void CURLAbortFile(void)
{
filedownload.http_running = false;
#ifdef HAVE_THREADS
// lock and unlock to wait for the download thread to exit
I_lock_mutex(&downloadmutex);
I_unlock_mutex(downloadmutex);
#endif
}
void CURLGetFile(void)
{
#ifdef HAVE_THREADS
I_lock_mutex(&downloadmutex);
#endif
CURLMcode mc; /* return code used by curl_multi_wait() */
CURLcode easyres; /* Return from easy interface */
CURLMsg *m; /* for picking up messages with the transfer status */
@@ -1453,7 +1459,9 @@ void CURLGetFile(void)
}
filedownload.http_running = false;
#ifdef HAVE_THREADS
I_unlock_mutex(downloadmutex);
#endif
}
HTTP_login *
+8
View File
@@ -13,6 +13,10 @@
#ifndef __D_NETFIL__
#define __D_NETFIL__
#ifdef __cplusplus
extern "C" {
#endif
#include "d_clisrv.h"
#include "w_wad.h"
@@ -125,4 +129,8 @@ HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next);
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream);
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __D_NETFIL__
+10 -4
View File
@@ -388,7 +388,7 @@ static void DRPC_GotServerIP(UINT32 address)
--------------------------------------------------*/
static const char *DRPC_GetServerIP(void)
{
const char *address;
const char *address;
// If you're connected
if (I_GetNodeAddress && (address = I_GetNodeAddress(servernode)) != NULL)
@@ -489,7 +489,7 @@ void DRPC_UpdatePresence(void)
{
#endif
discordPresence.state = "Private";
#ifdef MASTERSERVER
#ifdef MASTERSERVER
}
#endif
@@ -571,9 +571,15 @@ void DRPC_UpdatePresence(void)
{
// Map name on tool tip
char *title = G_BuildMapTitle(gamemap);
snprintf(mapname, 48, "Map: %s", title);
if (title)
{
snprintf(mapname, 48, "Map: %s", title);
Z_Free(title);
}
else
snprintf(mapname, 48, "Map: UNKNOWN");
discordPresence.largeImageText = mapname;
Z_Free(title);
}
if (gamestate == GS_LEVEL && Playing())
+18
View File
@@ -58,6 +58,9 @@
// warning C4152: nonstandard extension, function/data pointer conversion in expression
// warning C4213: nonstandard extension used : cast on l-value
#ifdef __cplusplus
extern "C" {
#endif
#include "doomtype.h"
@@ -524,12 +527,15 @@ UINT32 quickncasehash (const char *p, size_t n)
return x;
}
#ifndef __cplusplus
#ifndef min // Double-Check with WATTCP-32's cdefs.h
#define min(x, y) (((x) < (y)) ? (x) : (y))
#endif
#ifndef max // Double-Check with WATTCP-32's cdefs.h
#define max(x, y) (((x) > (y)) ? (x) : (y))
#endif
#endif
#ifndef CLAMP
#define CLAMP(x, y, z) ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x)))
#endif
@@ -560,6 +566,14 @@ UINT32 quickncasehash (const char *p, size_t n)
#define UNLIKELY(x) (x)
#endif
#ifdef __cplusplus
#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
#define restrict __restrict
#else
#define restrict
#endif
#endif
// An assert-type mechanism.
#ifdef PARANOIA
#define I_Assert(e) ((e) ? (void)0 : I_Error("assert failed: %s, file %s, line %d", #e, __FILE__, __LINE__))
@@ -657,4 +671,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
#undef UPDATE_ALERT
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __DOOMDEF__
+1 -1
View File
@@ -125,7 +125,7 @@ extern boolean lastdraw;
extern INT32 postimgparam[MAXSPLITSCREENPLAYERS];
extern INT32 viewwindowx, viewwindowy;
extern INT32 viewwidth, scaledviewwidth;
extern INT32 viewwidth;
extern boolean gamedataloaded;
+23 -16
View File
@@ -17,6 +17,10 @@
#ifndef __DOOMTYPE__
#define __DOOMTYPE__
#ifdef __cplusplus
extern "C" {
#endif
#if defined (_WIN32)
//#define WIN32_LEAN_AND_MEAN
#define RPC_NO_WINDOWS_H
@@ -100,8 +104,10 @@ typedef long ssize_t;
#define strnicmp(x,y,n) strncasecmp(x,y,n)
#endif
#ifndef __cplusplus
char *strcasestr(const char *in, const char *what);
#define stristr strcasestr
#endif
#if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap
#define true 1
@@ -156,22 +162,19 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
/* Boolean type definition */
// \note __BYTEBOOL__ used to be set above if "macintosh" was defined,
// if macintosh's version of boolean type isn't needed anymore, then isn't this macro pointless now?
#ifndef __BYTEBOOL__
#define __BYTEBOOL__
//faB: clean that up !!
#if defined( _MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 and forward
#include "stdbool.h"
#elif defined (_WIN32)
#define false FALSE // use windows types
#define true TRUE
#define boolean BOOL
#else
typedef enum {false, true} boolean;
#endif
#endif // __BYTEBOOL__
#ifndef _WIN32
#include <stdbool.h>
// dont use stdbools _BOOL type
// its smaller (1 byte) than the old interger bool (4 bytes)
// which results in packed struct sizes being mismatched between vanilla and this
// however we gotta still include stdbool cause since c23 true and false are keywords
// which we cant use as enumeration constants
typedef int32_t boolean;
#else
#define false FALSE
#define true TRUE
#define boolean BOOL
#endif
/* 7.18.2.1 Limits of exact-width integer types */
#ifndef INT8_MIN
@@ -385,4 +388,8 @@ unset_bit_array (bitarray_t * const array, const int value)
typedef UINT64 precise_t;
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__DOOMTYPE__
+3 -2
View File
@@ -531,8 +531,8 @@ static const char *credits[] = {
"\"Xyzzy\"",
"\"Chearii\"",
" ",
"\"Sunflower\" aka \"AnimeSonic\"",
"\"Yuz\" aka \"Yuzler\"",
"\"Sunflower\"",
"\"Yuz\"",
"\"Democrab\"",
"\"EXpand\"",
"\"Nexit\"",
@@ -543,6 +543,7 @@ static const char *credits[] = {
"\"Achii\"",
"\"Anonimus\"",
"\"scizor300\"",
"\"Lugent\"",
"",
"\1Special Thanks",
"SEGA",
+3 -3
View File
@@ -313,7 +313,7 @@ void F_WipeStartScreen(void)
return;
}
#endif
wipe_scr_start = screens[3];
wipe_scr_start = vid.screens[3];
I_ReadScreen(wipe_scr_start);
#endif
}
@@ -330,7 +330,7 @@ void F_WipeEndScreen(void)
return;
}
#endif
wipe_scr_end = screens[4];
wipe_scr_end = vid.screens[4];
I_ReadScreen(wipe_scr_end);
V_DrawBlock(0, 0, 0, vid.width, vid.height, wipe_scr_start);
#endif
@@ -353,7 +353,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
// Init the wipe
WipeInAction = true;
wipe_scr = screens[0];
wipe_scr = vid.screens[0];
// lastwipetic should either be 0 or the tic we last wiped
// on for fade-to-black
+8
View File
@@ -4,6 +4,10 @@
#ifndef __FILESRCH_H__
#define __FILESRCH_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "doomdef.h"
#include "d_netfil.h"
#include "m_menu.h" // MAXSTRINGLENGTH
@@ -96,4 +100,8 @@ void closefilemenu(boolean validsize);
void searchfilemenu(char *tempname);
boolean preparefilemenu(boolean samedepth, boolean replayhut);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __FILESRCH_H__
+41 -29
View File
@@ -385,7 +385,8 @@ consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, N
consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
// Display song credits
consvar_t cv_songcredits = {"songcredits", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t songcredits_cons_t[] = {{0, "Off"}, {1, "Default"}, {2, "Box"}, {0, NULL}};
consvar_t cv_songcredits = {"songcredits", "Default", CV_SAVE, songcredits_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// Show "FREE PLAY" when you're alone. :(
consvar_t cv_showfreeplay = { "showfreeplay", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -3998,7 +3999,6 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool
}
}
char *G_BuildMapTitle(INT32 mapnum)
{
char *title = NULL;
@@ -5465,33 +5465,36 @@ void G_GhostTicker(void)
break;
}
}
if (type == MT_GHOST)
if (type != -1)
{
mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
}
else
{
mobj = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
mobj->tics = -1; // nope.
mobj->color = g->mo->color;
if (g->mo->eflags & MFE_VERTICALFLIP)
if (type == MT_GHOST)
{
mobj->flags2 |= MF2_OBJECTFLIP;
mobj->eflags |= MFE_VERTICALFLIP;
mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
}
P_SetScale(mobj, g->mo->scale);
mobj->destscale = g->mo->scale;
else
{
mobj = P_SpawnMobj(g->mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
mobj->tics = -1; // nope.
mobj->color = g->mo->color;
if (g->mo->eflags & MFE_VERTICALFLIP)
{
mobj->flags2 |= MF2_OBJECTFLIP;
mobj->eflags |= MFE_VERTICALFLIP;
}
P_SetScale(mobj, g->mo->scale);
mobj->destscale = g->mo->scale;
}
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_UnsetThingPosition(mobj);
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
P_SetThingPosition(mobj);
mobj->fuse = 8;
P_SetTarget(&mobj->target, g->mo);
}
mobj->floorz = mobj->z;
mobj->ceilingz = mobj->z+mobj->height;
P_UnsetThingPosition(mobj);
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
P_SetThingPosition(mobj);
mobj->fuse = 8;
P_SetTarget(&mobj->target, g->mo);
}
if (ziptic & EZT_HIT)
{ // Spawn hit poofs for killing things!
@@ -6068,15 +6071,19 @@ void G_BeginRecording(void)
char *title = G_BuildMapTitle(gamemap);
// Print to a separate temp buffer instead of demo.titlename, so we can use it in M_TextInputSetString
snprintf(demotitlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername);
if (title)
{
snprintf(demotitlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername);
Z_Free(title);
}
else
snprintf(demotitlename, 64, "%s", modeattacking ? "Time Attack" : connectedservername);
// Init just in case it isn't initialized already
M_TextInputInit(&demo.titlenameinput, demo.titlename, sizeof(demo.titlename));
// This will indirectly assign to demo.titlename too
M_TextInputSetString(&demo.titlenameinput, demotitlename);
Z_Free(title);
}
// demo checksum
@@ -8137,7 +8144,7 @@ void G_SaveDemo(void)
size_t i, strindex = 0;
boolean dash = true;
for (i = 0; i < 127 && demo.titlename[i]; i++)
for (i = 0; demo.titlename[i] && i < 127; i++)
{
if ((demo.titlename[i] >= 'a' && demo.titlename[i] <= 'z') ||
(demo.titlename[i] >= '0' && demo.titlename[i] <= '9'))
@@ -8228,6 +8235,11 @@ boolean G_DemoTitleResponder(event_t *ev)
void G_SetGamestate(gamestate_t newstate)
{
gamestate = newstate;
//HACK: reset musiccredits whenever we change gamestate
// since we allow them to run everywhere now
S_ResetMusicCredit();
#ifdef HAVE_DISCORDRPC
DRPC_UpdatePresence();
#endif
+8
View File
@@ -14,6 +14,10 @@
#ifndef __G_GAME__
#define __G_GAME__
#ifdef __cplusplus
extern "C" {
#endif
#include "doomdef.h"
#include "doomstat.h"
#include "d_event.h"
@@ -484,4 +488,8 @@ void G_AddMapToBuffer(INT16 map);
void G_FixCamera(UINT8 view);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+1 -1
View File
@@ -1030,7 +1030,7 @@ INT32 G_KeyStringtoNum(const char *keystr)
if (!keystr[0])
return 0;
if (!keystr[0] || (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z'))
if (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z')
return keystr[0];
if (!strncmp(keystr, "KEY", 3) && keystr[3] >= '0' && keystr[3] <= '9')
+13 -32
View File
@@ -89,32 +89,23 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
{
if (!pSurf)
{
I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to
I_Error("Got a null FSurfaceInfo in batching"); // nulls should not come in the stuff that batching currently applies to
}
if (polygonArraySize == polygonArrayAllocSize)
{
PolygonArrayEntry* new_array;
// ran out of space, make new array double the size
// ran out of space, double the array size
polygonArrayAllocSize *= 2;
new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry));
memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry));
free(polygonArray);
polygonArray = new_array;
polygonArray = realloc(polygonArray, polygonArrayAllocSize * sizeof(PolygonArrayEntry));
// also need to redo the index array, dont need to copy it though
free(polygonArraySorted);
polygonArraySorted = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry *));
polygonArraySorted = realloc(polygonArraySorted, polygonArrayAllocSize * sizeof(PolygonArrayEntry*));
}
while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize)
{
FOutVector* new_array;
// need more space for vertices in unsortedVertexArray
unsortedVertexArrayAllocSize *= 2;
new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector));
free(unsortedVertexArray);
unsortedVertexArray = new_array;
unsortedVertexArray = realloc(unsortedVertexArray, unsortedVertexArrayAllocSize * sizeof(FOutVector));
}
// add the polygon data to the arrays
@@ -124,7 +115,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_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
polygonArray[polygonArraySize].shader = (shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
polygonArraySize++;
@@ -140,8 +131,8 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
static int comparePolygons(const void *p1, const void *p2)
{
PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
const PolygonArrayEntry *poly1 = *(PolygonArrayEntry *const *)p1;
const PolygonArrayEntry *poly2 = *(PolygonArrayEntry *const *)p2;
int diff;
INT64 diff64;
@@ -177,9 +168,7 @@ static int comparePolygons(const void *p1, const void *p2)
diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end;
if (diff != 0) return diff;
diff = poly1->surf.LightInfo.directional - poly2->surf.LightInfo.directional;
return diff;
return poly1->surf.LightInfo.directional - poly2->surf.LightInfo.directional;
}
static int comparePolygonsNoShaders(const void *p1, const void *p2)
@@ -328,19 +317,11 @@ void HWR_RenderBatches(void)
// probably never will this loop run more than once though
while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize)
{
FOutVector* new_array;
unsigned int* new_index_array;
finalVertexArrayAllocSize *= 2;
new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector));
free(finalVertexArray);
finalVertexArray = new_array;
finalVertexArray = realloc(finalVertexArray, finalVertexArrayAllocSize * sizeof(FOutVector));
// also increase size of index array, 3x of vertex array since
// going from fans to triangles increases vertex count to 3x
new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32));
memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32));
free(finalVertexIndexArray);
finalVertexIndexArray = new_index_array;
finalVertexIndexArray = realloc(finalVertexIndexArray, finalVertexArrayAllocSize * 3 * sizeof(UINT32));
}
// write the vertices of the polygon
memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[entry->vertsIndex],
@@ -396,8 +377,8 @@ void HWR_RenderBatches(void)
currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba ||
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end ||
currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional)
{
changeState = true;
+14 -9
View File
@@ -46,12 +46,16 @@ RGBA_t *HWR_GetTexturePalette(void)
static INT32 format2bpp(GLTextureFormat_t format)
{
if (format == GL_TEXFMT_RGBA)
return 4;
else if (format == GL_TEXFMT_ALPHA_INTENSITY_88 || format == GL_TEXFMT_AP_88)
return 2;
else
return 1;
switch (format)
{
case GL_TEXFMT_RGBA:
return 4;
case GL_TEXFMT_ALPHA_INTENSITY_88:
case GL_TEXFMT_AP_88:
return 2;
default:
return 1;
}
}
// This code was originally placed directly in HWR_DrawPatchInCache.
@@ -221,8 +225,6 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
if (texture->width <= 0 || texture->height <= 0)
return;
palette = HWR_GetTexturePalette();
x1 = patch->originx;
width = SHORT(realpatch->width);
height = SHORT(realpatch->height);
@@ -234,6 +236,8 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap,
if (patch->originy > texture->height || (patch->originy + height) < 0)
return; // patch not located within texture's y bounds, ignore
palette = HWR_GetTexturePalette();
// patch is actually inside the texture!
// now check if texture is partly off-screen and adjust accordingly
@@ -323,7 +327,6 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *gltex, boolean noe
boolean skyspecial = false; // poor hack for Legacy large skies..
RGBA_t *palette;
palette = HWR_GetTexturePalette();
texture = textures[texnum];
@@ -361,6 +364,8 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *gltex, boolean noe
INT32 j;
RGBA_t col;
palette = HWR_GetTexturePalette();
col = palette[HWR_CHROMAKEY_EQUIVALENTCOLORINDEX];
for (idx = 0, j = 0; j < blockheight; j++)
+2
View File
@@ -318,6 +318,8 @@ enum hwdsetspecialstate
HWD_SET_TEXTUREFILTERMODE,
HWD_SET_TEXTUREANISOTROPICMODE,
HWD_SET_WIREFRAME,
HWD_SET_MSAA,
HWD_SET_SCREEN_TEXTURES,
+34 -25
View File
@@ -96,12 +96,12 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
pdupx = pdupy = 2.0f;
break;
case V_SMALLSCALEPATCH:
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx);
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy);
pdupx = 2.0f * FIXED_TO_FLOAT(vid.smalldupx*FRACUNIT);
pdupy = 2.0f * FIXED_TO_FLOAT(vid.smalldupy*FRACUNIT);
break;
case V_MEDSCALEPATCH:
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx);
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy);
pdupx = 2.0f * FIXED_TO_FLOAT(vid.meddupx*FRACUNIT);
pdupy = 2.0f * FIXED_TO_FLOAT(vid.meddupx*FRACUNIT);
break;
}
@@ -241,16 +241,16 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
if (option & V_SNAPTORIGHT)
cx += (fvw - (FLOATBASEVIDWIDTH * dupx));
else if (!(option & V_SNAPTOLEFT))
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2;
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2.0f;
}
if (fabsf(fvh - FLOATBASEVIDHEIGHT * dupy) > 1.0E-36f)
{
if ((option & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP))
cy += (fvh/2 - (FLOATBASEVIDHEIGHT/2 * dupy));
cy += (fvh/2.0f - (FLOATBASEVIDHEIGHT/2.0f * dupy));
else if (option & V_SNAPTOBOTTOM)
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
else if (!(option & V_SNAPTOTOP))
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2;
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2.0f;
}
}
}
@@ -305,10 +305,13 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
FSurfaceInfo Surf;
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans];
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans];
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans];
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
switch (alphalevel)
{
case 13: Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans]; break;
case 14: Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans]; break;
case 15: Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans]; break;
default: Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; break;
}
flags |= PF_Modulated;
GL_DrawPolygon(&Surf, v, 4, flags);
@@ -392,16 +395,16 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
if (option & V_SNAPTORIGHT)
cx += (fvw - (FLOATBASEVIDWIDTH * dupx));
else if (!(option & V_SNAPTOLEFT))
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2;
cx += (fvw - (FLOATBASEVIDWIDTH * dupx))/2.0f;
}
if (fabsf(fvh - FLOATBASEVIDHEIGHT * dupy) > 1.0E-36f)
{
if ((option & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP))
cy += (fvh/2 - (FLOATBASEVIDHEIGHT/2 * dupy));
cy += (fvh/2.0f - (FLOATBASEVIDHEIGHT/2.0f * dupy));
else if (option & V_SNAPTOBOTTOM)
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
else if (!(option & V_SNAPTOTOP))
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2;
cy += (fvh - (FLOATBASEVIDHEIGHT * dupy))/2.0f;
}
}
}
@@ -467,10 +470,13 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
FSurfaceInfo Surf;
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value];
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[cv_translucenthud.value];
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value];
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
switch (alphalevel)
{
case 13: Surf.PolyColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; break;
case 14: Surf.PolyColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; break;
case 15: Surf.PolyColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; break;
default: Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; break;
}
flags |= PF_Modulated;
GL_DrawPolygon(&Surf, v, 4, flags);
@@ -487,7 +493,7 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
// --------------------------------------------------------------------------
// Fills a box of pixels using a flat texture as a pattern
// --------------------------------------------------------------------------
void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum)
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum)
{
FOutVector v[4];
double dflatsize;
@@ -840,7 +846,7 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
if (color & V_SNAPTORIGHT)
fx += (fvw - (FLOATBASEVIDWIDTH * dupx));
else if (!(color & V_SNAPTOLEFT))
fx += (fvw - (FLOATBASEVIDWIDTH * dupx)) / 2;
fx += (fvw - (FLOATBASEVIDWIDTH * dupx)) / 2.0f;
}
if (fabsf(fvh - (FLOATBASEVIDHEIGHT * dupy)) > 1.0E-36f)
{
@@ -848,7 +854,7 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color)
if (color & V_SNAPTOBOTTOM)
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy));
else if (!(color & V_SNAPTOTOP))
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy)) / 2;
fy += (fvh - (FLOATBASEVIDHEIGHT * dupy)) / 2.0f;
}
}
@@ -1122,10 +1128,13 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
if (alphalevel)
{
if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans];
else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans];
else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans];
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
switch (alphalevel)
{
case 13: Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans]; break;
case 14: Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans]; break;
case 15: Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans]; break;
default: Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; break;
}
}
GL_DrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
+44 -45
View File
@@ -226,6 +226,8 @@ consvar_t cv_glsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL,
consvar_t cv_glbatching = {"gr_batching", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glwireframe = {"gr_wireframe", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glrenderdistance = {"gr_renderdistance", "Max", CV_SAVE, glrenderdistance_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_glhorizonlines = {"gr_horizonlines", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -338,6 +340,11 @@ static void HWR_SetShaderState(void)
GL_SetSpecialState(HWD_SET_SHADERS, HWR_UseShader() ? 1 : 0);
}
static boolean HWR_IsWireframeMode(void)
{
return (cv_glwireframe.value /*&& cv_debug*/);
}
static boolean HWR_OverrideObjectLightLevel(mobj_t *thing, INT32 *lightlevel)
{
if (R_ThingIsFullBright(thing))
@@ -541,7 +548,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
size_t len;
float tempxsow, tempytow;
float scrollx = 0.0f, scrolly = 0.0f;
float scrollx = 0.0f, scrolly = 0.0f, anglef = 0.0f;
angle_t angle = 0;
static FOutVector *planeVerts = NULL;
@@ -661,14 +668,11 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
if (angle) // Only needs to be done if there's an altered angle
{
angle = InvAngle(angle)>>ANGLETOFINESHIFT;
// This needs to be done so everything aligns after rotation
// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
tempxsow = FloatToFixed(flatxref);
tempytow = FloatToFixed(flatyref);
flatxref = (FixedToFloat(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
flatyref = (FixedToFloat(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
tempxsow = flatxref;
tempytow = flatyref;
anglef = ANG2RAD(InvAngle(angle));
flatxref = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));
flatyref = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));
}
#define SETUP3DVERT(vert, vx, vy) {\
@@ -679,10 +683,10 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
/* Need to rotate before translate */\
if (angle) /* Only needs to be done if there's an altered angle */\
{\
tempxsow = FloatToFixed(vert->s);\
tempytow = FloatToFixed(vert->t);\
vert->s = (FixedToFloat(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\
vert->t = (FixedToFloat(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\
tempxsow = vert->s;\
tempytow = vert->t;\
vert->s = (tempxsow * cos(anglef)) - (tempytow * sin(anglef));\
vert->t = (tempxsow * sin(anglef)) + (tempytow * cos(anglef));\
}\
\
vert->x = (vx);\
@@ -4227,7 +4231,6 @@ static void *HWR_CreateDrawNode(gl_drawnode_type_t type)
Z_Realloc(drawnodes, alloceddrawnodes * sizeof(gl_drawnode_t), PU_LEVEL, &drawnodes);
}
drawnode = &drawnodes[numdrawnodes++];
drawnode->type = type;
@@ -4458,7 +4461,10 @@ static void HWR_DrawModels(void)
continue;
}
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
if (!spr->mobj)
continue;
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
{
md2_t *md2;
@@ -5259,6 +5265,9 @@ static void HWR_DrawSkyBackground(void)
if (drewsky)
return;
if (HWR_IsWireframeMode())
return;
GL_SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated);
memcpy(&dometransform, &atransform, sizeof(FTransform));
@@ -5461,8 +5470,8 @@ void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, player_t *pl
HWR_PortalClipping(rootportal);
}
// Set transform.
GL_SetTransform(&atransform);
if (HWR_IsWireframeMode())
GL_SetSpecialState(HWD_SET_WIREFRAME, 1);
ps_numbspcalls.value.i = 0;
ps_numpolyobjects.value.i = 0;
@@ -5527,6 +5536,9 @@ void HWR_RenderViewpoint(gl_portal_t *rootportal, const float fpov, player_t *pl
ps_hw_nodedrawtime.value.p = 0;
HWR_RenderDrawNodes();
if (HWR_IsWireframeMode())
GL_SetSpecialState(HWD_SET_WIREFRAME, 0);
HWR_FreePortalList(portallist);
}
@@ -5552,28 +5564,12 @@ static void HWR_RenderFrame(player_t *player, boolean skybox)
gl_viewwindowx += gl_viewwidth;
}
if (splitscreen == 2 && player == &players[displayplayers[2]])
{
// V_DrawPatchFill, but for the fourth screen only
patch_t *gpatch = W_CachePatchName("SRB2BACK", PU_PATCH);
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
INT32 x, y, pw = (gpatch->width * dupz), ph = (gpatch->height * dupz);
for (x = vid.width >> 1; x < vid.width; x += pw)
{
for (y = vid.height >> 1; y < vid.height; y += ph)
HWR_DrawStretchyFixedPatch(gpatch, (x)<<FRACBITS, (y)<<FRACBITS, FRACUNIT, FRACUNIT, V_NOSCALESTART, NULL, 0);
}
}
// check for new console commands.
NetUpdate();
// Clear view, set viewport (glViewport), set perspective...
HWR_ClearView();
ST_doPaletteStuff();
// Draw the sky background.
HWR_DrawSkyBackground();
if (skybox)
@@ -5730,6 +5726,7 @@ void HWR_LoadLevel(boolean reloadinggamestate)
static void HWR_TogglePaletteRendering(void)
{
V_ResetPaletteCVars(); // dont carry over changed palettes
ST_ResetPaletteStuff();
// which state should we go to?
if (HWR_ShouldUsePaletteRendering())
@@ -5750,7 +5747,7 @@ static void HWR_TogglePaletteRendering(void)
// 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.
GL_ClearMipMapCache();
HWR_LoadMapTextures(numtextures);
}
}
else
@@ -5764,7 +5761,7 @@ static void HWR_TogglePaletteRendering(void)
// 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.
GL_ClearMipMapCache();
HWR_LoadMapTextures(numtextures);
}
}
}
@@ -5801,6 +5798,8 @@ void HWR_AddCommands(void)
CV_RegisterVar(&cv_glbatching);
CV_RegisterVar(&cv_glwireframe);
CV_RegisterVar(&cv_glrenderdistance);
CV_RegisterVar(&cv_glhorizonlines);
@@ -5873,7 +5872,6 @@ static void COM_HWR_glinfo(void)
CONS_Printf("Unrecognized argument: %s\n", argv);
return;
}
}
CONS_Printf("\x88OpenGL %s\x80\n", gl_version);
@@ -5993,19 +5991,19 @@ static void HWR_DoPostProcessor(player_t *player)
if (cv_glscreentextures.value != 2) // screen textures are needed for the rest of the effects
return;
// Capture the screen for intermission and screen waving
if (gamestate != GS_INTERMISSION)
GL_MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
if (splitscreen) // Not supported in splitscreen - someone want to add support?
return;
//UINT8 viewnum = R_GetViewNumber(); // see above
//UINT8 viewnum = R_GetViewNumber(); // see below
//camera_t *thiscam = &camera[viewnum];
camera_t *thiscam = &camera[0];
// Not supported in splitscreen - someone want to add support?
const boolean screenwave = (!splitscreen && (thiscam->postimg & POSTIMG_WATER || thiscam->postimg & POSTIMG_HEAT));
// Capture the screen for intermission and screen waving
if ((lastdraw || screenwave) && gamestate != GS_INTERMISSION)
GL_MakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1);
// Drunken vision! WooOOooo~
if (thiscam->postimg & POSTIMG_WATER || thiscam->postimg & POSTIMG_HEAT)
if (screenwave)
{
// 10 by 10 grid. 2 coordinates (xy)
float v[SCREENVERTS][SCREENVERTS][2];
@@ -6039,6 +6037,7 @@ static void HWR_DoPostProcessor(player_t *player)
v[x][y][1] = (y/((float)(SCREENVERTS-1.0f)/9.0f))-4.5f;
}
}
GL_PostImgRedraw(v);
// Capture the screen again for screen waving on the intermission
+11 -1
View File
@@ -34,6 +34,10 @@
#define GLENCORE
#ifdef __cplusplus
extern "C" {
#endif
// Startup & Shutdown the hardware mode renderer
void HWR_Startup(void);
void HWR_Shutdown(void);
@@ -202,6 +206,8 @@ extern consvar_t cv_glsolvetjoin;
extern consvar_t cv_glbatching;
extern consvar_t cv_glwireframe;
extern consvar_t cv_glrenderdistance;
extern consvar_t cv_glhorizonlines;
@@ -223,7 +229,11 @@ FUNCINLINE static ATTRINLINE boolean HWR_ShouldUsePaletteRendering(void)
FUNCINLINE static ATTRINLINE boolean HWR_PalRenderFlashpal(void)
{
return (HWR_ShouldUsePaletteRendering() && cv_glflashpal.value);
return (cv_glflashpal.value && HWR_ShouldUsePaletteRendering());
}
#ifdef __cplusplus
}// extern "C"
#endif
#endif
+8
View File
@@ -15,6 +15,10 @@
#ifndef _HW_MD2_H_
#define _HW_MD2_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "hw_glob.h"
#include "hw_model.h"
@@ -46,4 +50,8 @@ void HWR_DrawMD2(gl_vissprite_t *spr);
void HWR_AddPlayerMD2(INT32 skin, boolean local);
void HWR_AddSpriteMD2(size_t spritenum);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // _HW_MD2_H_
+2 -2
View File
@@ -66,6 +66,7 @@ void HWR_FreePortalList(gl_portallist_t freelist)
// free memory from portal list allocated by calls to Add2Lines
gl_portal_t *gl_portal_temp = freelist.base;
while (gl_portal_temp)
{
gl_portal_t *nextportal = gl_portal_temp->next;
@@ -125,8 +126,7 @@ void HWR_PortalFrame(gl_portal_t* portal)
if (portal->clipline != -1)
{
portalclipline = &lines[portal->clipline];
portalcullsector = portalclipline->frontsector;
viewsector = portalclipline->frontsector;
portalcullsector = viewsector = portalclipline->frontsector;
}
else
{
+183 -138
View File
@@ -350,6 +350,8 @@ typedef void (APIENTRY * PFNglDisable) (GLenum cap);
static PFNglDisable pglDisable;
typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params);
static PFNglGetFloatv pglGetFloatv;
typedef void (APIENTRY * PFNglPolygonMode) (GLenum, GLenum);
static PFNglPolygonMode pglPolygonMode;
/* Depth Buffer */
typedef void (APIENTRY * PFNglClearDepth) (GLclampd depth);
@@ -549,6 +551,7 @@ boolean SetupGLfunc(void)
GETOPENGLFUNC(pglGetFloatv, glGetFloatv)
GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv)
GETOPENGLFUNC(pglGetString, glGetString)
GETOPENGLFUNC(pglPolygonMode, glPolygonMode)
GETOPENGLFUNC(pglClearDepth, glClearDepth)
GETOPENGLFUNC(pglDepthFunc, glDepthFunc)
@@ -734,69 +737,78 @@ static boolean GLFramebuffer_CheckExt(void)
return false;
// check if all needed gl extensions are available
return (GL_isExtAvailable("GL_ARB_framebuffer_no_attachments", gl_extensions) && GL_isExtAvailable("GL_ARB_framebuffer_object", gl_extensions) && GL_isExtAvailable("GL_ARB_framebuffer_sRGB", gl_extensions));
return (GL_isExtAvailable("GL_ARB_framebuffer_no_attachments", gl_extensions)
&& GL_isExtAvailable("GL_ARB_framebuffer_object", gl_extensions)
&& GL_isExtAvailable("GL_ARB_framebuffer_sRGB", gl_extensions));
}
#endif
void SetupGLFunc4(void)
{
#define GetGLfunc(func) \
p##func = GetGLFunc(#func); \
if (!p##func) \
{ \
GL_MSG_Warning("failed to get OpenGL function: %s", #func); \
} \
/* 1.2 funcs */
pglTexImage3D = GetGLFunc("glTexImage3D");
GetGLfunc(glTexImage3D);
/* 1.3 funcs */
pglActiveTexture = GetGLFunc("glActiveTexture");
pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f");
pglClientActiveTexture = GetGLFunc("glClientActiveTexture");
pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv");
GetGLfunc(glActiveTexture);
GetGLfunc(glMultiTexCoord2f);
GetGLfunc(glClientActiveTexture);
GetGLfunc(glMultiTexCoord2fv);
/* 1.5 funcs */
pglGenBuffers = GetGLFunc("glGenBuffers");
pglBindBuffer = GetGLFunc("glBindBuffer");
pglBufferData = GetGLFunc("glBufferData");
pglDeleteBuffers = GetGLFunc("glDeleteBuffers");
pglColorPointer = GetGLFunc("glColorPointer");
GetGLfunc(glGenBuffers);
GetGLfunc(glBindBuffer);
GetGLfunc(glBufferData);
GetGLfunc(glDeleteBuffers);
GetGLfunc(glColorPointer);
/* 2.0 funcs */
pglBlendEquation = GetGLFunc("glBlendEquation");
GetGLfunc(glBlendEquation);
pglStencilFuncSeparate = GetGLFunc("glStencilFuncSeparate");
pglStencilOpSeparate = GetGLFunc("glStencilOpSeparate");
GetGLfunc(glStencilFuncSeparate);
GetGLfunc(glStencilOpSeparate);
pglCreateShader = GetGLFunc("glCreateShader");
pglShaderSource = GetGLFunc("glShaderSource");
pglCompileShader = GetGLFunc("glCompileShader");
pglGetShaderiv = GetGLFunc("glGetShaderiv");
pglGetShaderInfoLog = GetGLFunc("glGetShaderInfoLog");
pglDeleteShader = GetGLFunc("glDeleteShader");
pglCreateProgram = GetGLFunc("glCreateProgram");
pglDeleteProgram = GetGLFunc("glDeleteProgram");
pglAttachShader = GetGLFunc("glAttachShader");
pglLinkProgram = GetGLFunc("glLinkProgram");
pglGetProgramiv = GetGLFunc("glGetProgramiv");
pglGetProgramInfoLog = GetGLFunc("glGetProgramInfoLog");
pglUseProgram = GetGLFunc("glUseProgram");
pglUniform1i = GetGLFunc("glUniform1i");
pglUniform1f = GetGLFunc("glUniform1f");
pglUniform2f = GetGLFunc("glUniform2f");
pglUniform3f = GetGLFunc("glUniform3f");
pglUniform4f = GetGLFunc("glUniform4f");
pglUniform1fv = GetGLFunc("glUniform1fv");
pglUniform2fv = GetGLFunc("glUniform2fv");
pglUniform3fv = GetGLFunc("glUniform3fv");
pglGetUniformLocation = GetGLFunc("glGetUniformLocation");
GetGLfunc(glCreateShader);
GetGLfunc(glShaderSource);
GetGLfunc(glCompileShader);
GetGLfunc(glGetShaderiv);
GetGLfunc(glGetShaderInfoLog);
GetGLfunc(glDeleteShader);
GetGLfunc(glCreateProgram);
GetGLfunc(glDeleteProgram);
GetGLfunc(glAttachShader);
GetGLfunc(glLinkProgram);
GetGLfunc(glGetProgramiv);
GetGLfunc(glGetProgramInfoLog);
GetGLfunc(glUseProgram);
GetGLfunc(glUniform1i);
GetGLfunc(glUniform1f);
GetGLfunc(glUniform2f);
GetGLfunc(glUniform3f);
GetGLfunc(glUniform4f);
GetGLfunc(glUniform1fv);
GetGLfunc(glUniform2fv);
GetGLfunc(glUniform3fv);
GetGLfunc(glGetUniformLocation);
#ifdef USE_FBO_OGL
if (GLFramebuffer_CheckExt())
{
pglGenFramebuffers = GetGLFunc("glGenFramebuffers");
pglBindFramebuffer = GetGLFunc("glBindFramebuffer");
pglDeleteFramebuffers = GetGLFunc("glDeleteFramebuffers");
pglFramebufferTexture2D = GetGLFunc("glFramebufferTexture2D");
pglCheckFramebufferStatus = GetGLFunc("glCheckFramebufferStatus");
pglGenRenderbuffers = GetGLFunc("glGenRenderbuffers");
pglBindRenderbuffer = GetGLFunc("glBindRenderbuffer");
pglDeleteRenderbuffers = GetGLFunc("glDeleteRenderbuffers");
pglRenderbufferStorage = GetGLFunc("glRenderbufferStorage");
pglFramebufferRenderbuffer = GetGLFunc("glFramebufferRenderbuffer");
GetGLfunc(glGenFramebuffers);
GetGLfunc(glBindFramebuffer);
GetGLfunc(glDeleteFramebuffers);
GetGLfunc(glFramebufferTexture2D);
GetGLfunc(glCheckFramebufferStatus);
GetGLfunc(glGenRenderbuffers);
GetGLfunc(glBindRenderbuffer);
GetGLfunc(glDeleteRenderbuffers);
GetGLfunc(glRenderbufferStorage);
GetGLfunc(glFramebufferRenderbuffer);
// check if ALL functions are availible
if (pglGenFramebuffers && pglBindFramebuffer &&
@@ -807,6 +819,7 @@ void SetupGLFunc4(void)
supportFBO = true;
}
#endif
#undef GetGLfunc
}
boolean GL_InitShaders(void)
@@ -956,6 +969,7 @@ static void GL_SetNoTexture(void)
{
if (NOTEXTURE_NUM == 0)
pglGenTextures(1, &NOTEXTURE_NUM);
pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM);
tex_downloaded = NOTEXTURE_NUM;
}
@@ -1105,10 +1119,12 @@ void GL_DeleteTexture(GLMipmap_t *pTexInfo)
head->next->prev = head->prev;
else // no next -> tail is being deleted -> update TexCacheTail
TexCacheTail = head->prev;
if (head->prev)
head->prev->next = head->next;
else // no prev -> head is being deleted -> update TexCacheHead
TexCacheHead = head->next;
free(head);
break;
}
@@ -1129,7 +1145,7 @@ static void GL_Framebuffer_GenerateAttachments(void)
pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject);
// Generate the framebuffer texture
if (FramebufferTexture == 0)
if (!FramebufferTexture)
{
pglGenTextures(1, &FramebufferTexture);
pglBindTexture(GL_TEXTURE_2D, FramebufferTexture);
@@ -1143,7 +1159,7 @@ static void GL_Framebuffer_GenerateAttachments(void)
}
// Generate the renderbuffer
if (RenderbufferObject == 0)
if (!RenderbufferObject)
{
pglGenRenderbuffers(1, &RenderbufferObject);
@@ -1165,10 +1181,10 @@ static void GL_Framebuffer_GenerateAttachments(void)
static void GL_Framebuffer_DeleteAttachments(void)
{
if (!supportFBO || fboinit == false)
if (!supportFBO || !fboinit)
return;
if (FramebufferObject == 0 && RenderbufferObject == 0 && FramebufferTexture == 0)
if (!FramebufferObject && !RenderbufferObject && !FramebufferTexture)
return;
// Unbind the framebuffer
@@ -1192,7 +1208,7 @@ static void GL_Framebuffer_Generate(void)
return;
// Generate the framebuffer
if (FramebufferObject == 0)
if (!FramebufferObject)
pglGenFramebuffers(1, &FramebufferObject);
if (pglCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
@@ -1201,7 +1217,7 @@ static void GL_Framebuffer_Generate(void)
static void GL_Framebuffer_Delete(void)
{
if (!supportFBO || fboinit == false)
if (!supportFBO || !fboinit)
return;
if (FramebufferObject)
@@ -1213,10 +1229,10 @@ static void GL_Framebuffer_Delete(void)
void GL_Framebuffer_Unbind(void)
{
if (!supportFBO || fboinit == false)
if (!supportFBO || !fboinit)
return;
if (FramebufferObject == 0 && RenderbufferObject == 0)
if (!FramebufferObject && !RenderbufferObject)
return;
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -1230,7 +1246,7 @@ void GL_Framebuffer_Enable(void)
if (FramebufferObject == 0)
GL_Framebuffer_Generate();
else if (FramebufferTexture == 0 || RenderbufferObject == 0)
else if (!FramebufferTexture || !RenderbufferObject)
GL_Framebuffer_GenerateAttachments();
pglBindFramebuffer(GL_FRAMEBUFFER, FramebufferObject);
@@ -1239,10 +1255,10 @@ void GL_Framebuffer_Enable(void)
void GL_Framebuffer_Disable(void)
{
if (!supportFBO || fboinit == false)
if (!supportFBO || !fboinit)
return;
if (FramebufferObject == 0 && RenderbufferObject == 0)
if (!FramebufferObject && !RenderbufferObject)
return;
pglBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -1292,20 +1308,29 @@ INT32 GL_isExtAvailable(const char *extension, const GLubyte *start)
{
GLubyte *where, *terminator;
if (!extension || !start) return 0;
if (!extension || !start)
return 0;
where = (GLubyte *) strchr(extension, ' ');
if (where || *extension == '\0')
return 0;
for (;;)
{
where = (GLubyte *) strstr((const char *) start, extension);
if (!where)
break;
terminator = where + strlen(extension);
if (where == start || *(where - 1) == ' ')
{
if (*terminator == ' ' || *terminator == '\0')
return 1;
}
start = terminator;
}
return 0;
@@ -1337,23 +1362,33 @@ void GL_ReadScreenTexture(int tex, UINT16 *dst_data)
{
INT32 i;
int dst_stride = screen_width * 3; // stride between rows of image data
GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (screen_height - 1);
GLubyte *top, *bottom;
GLubyte *row;
row = malloc(dst_stride);
if (!row) return;
if (!row)
return;
top = (GLvoid*)dst_data;
bottom = top + dst_stride * (screen_height - 1);
// at the time this function is called, generic2 can be found drawn on the framebuffer
// if some other screen texture is needed, draw it to the framebuffer
// and draw generic2 back after reading the framebuffer.
// this hack is for some reason **much** faster than the simple solution of using glGetTexImage.
if (tex != HWD_SCREENTEXTURE_GENERIC2)
GL_DrawScreenTexture(tex, NULL, 0);
pglPixelStorei(GL_PACK_ALIGNMENT, 1);
pglReadPixels(0, 0, screen_width, screen_height, GL_RGB, GL_UNSIGNED_BYTE, dst_data);
if (tex != HWD_SCREENTEXTURE_GENERIC2)
GL_DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0);
// Flip image upside down.
// In other words, convert OpenGL's "bottom->top" row order into "top->bottom".
for(i = 0; i < screen_height/2; i++)
for (i = 0; i < screen_height/2; i++)
{
memcpy(row, top, dst_stride);
memcpy(top, bottom, dst_stride);
@@ -1361,6 +1396,7 @@ void GL_ReadScreenTexture(int tex, UINT16 *dst_data)
top += dst_stride;
bottom -= dst_stride;
}
free(row);
}
@@ -1413,10 +1449,8 @@ void GL_ClearBuffer(FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask
if (ColorMask)
{
if (ClearColor)
pglClearColor(ClearColor->red,
ClearColor->green,
ClearColor->blue,
ClearColor->alpha);
pglClearColor(ClearColor->red, ClearColor->green, ClearColor->blue, ClearColor->alpha);
ClearMask |= GL_COLOR_BUFFER_BIT;
}
if (DepthMask)
@@ -1431,6 +1465,7 @@ void GL_ClearBuffer(FBOOLEAN ColorMask, FBOOLEAN DepthMask, FBOOLEAN StencilMask
if (StencilMask)
ClearMask |= GL_STENCIL_BUFFER_BIT;// looks like sometimes stencil buffer needs clearing? had a problem with random black screens
pglClear(ClearMask);
pglEnableClientState(GL_VERTEX_ARRAY); // We always use this one
pglEnableClientState(GL_TEXTURE_COORD_ARRAY); // And mostly this one, too
@@ -2055,7 +2090,7 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
pglGetShaderInfoLog(gl_fragShader, 512, NULL, info_log);
pglGetShaderInfoLog(gl_fragShader, 512, NULL, info_log);
GL_MSG_Error("Error compiling fragment shader: %s\n", info_log);
pglDeleteShader(gl_vertShader);
@@ -2093,25 +2128,25 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
#define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform);
// lighting
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
shader->uniforms[gluniform_light_dir] = GETUNI("light_dir");
shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast");
shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight");
shader->uniforms[gluniform_poly_color] = GETUNI("poly_color");
shader->uniforms[gluniform_tint_color] = GETUNI("tint_color");
shader->uniforms[gluniform_fade_color] = GETUNI("fade_color");
shader->uniforms[gluniform_lighting] = GETUNI("lighting");
shader->uniforms[gluniform_fade_start] = GETUNI("fade_start");
shader->uniforms[gluniform_fade_end] = GETUNI("fade_end");
shader->uniforms[gluniform_light_dir] = GETUNI("light_dir");
shader->uniforms[gluniform_light_contrast] = GETUNI("light_contrast");
shader->uniforms[gluniform_light_backlight] = GETUNI("light_backlight");
// palette rendering
shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex");
shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex");
shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex");
shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex");
shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex");
shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex");
shader->uniforms[gluniform_scr_resolution] = GETUNI("scr_resolution");
shader->uniforms[gluniform_scr_resolution] = GETUNI("scr_resolution");
// misc.
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
#undef GETUNI
// set permanent uniform values
@@ -2319,49 +2354,54 @@ void GL_SetSpecialState(hwdspecialstate_t IdState, INT32 Value)
gl_allowshaders = Value;
break;
case HWD_SET_TEXTUREFILTERMODE:
switch (Value)
{
case HWD_SET_TEXTUREFILTER_TRILINEAR:
min_filter = GL_LINEAR_MIPMAP_LINEAR;
mag_filter = GL_LINEAR;
MipMap = GL_TRUE;
break;
case HWD_SET_TEXTUREFILTER_BILINEAR:
min_filter = mag_filter = GL_LINEAR;
switch (Value)
{
case HWD_SET_TEXTUREFILTER_TRILINEAR:
min_filter = GL_LINEAR_MIPMAP_LINEAR;
mag_filter = GL_LINEAR;
MipMap = GL_TRUE;
break;
case HWD_SET_TEXTUREFILTER_BILINEAR:
min_filter = mag_filter = GL_LINEAR;
MipMap = GL_FALSE;
break;
case HWD_SET_TEXTUREFILTER_POINTSAMPLED:
min_filter = mag_filter = GL_NEAREST;
MipMap = GL_FALSE;
break;
case HWD_SET_TEXTUREFILTER_MIXED1:
min_filter = GL_NEAREST;
mag_filter = GL_LINEAR;
MipMap = GL_FALSE;
break;
case HWD_SET_TEXTUREFILTER_MIXED2:
min_filter = GL_LINEAR;
mag_filter = GL_NEAREST;
MipMap = GL_FALSE;
break;
case HWD_SET_TEXTUREFILTER_MIXED3:
min_filter = GL_LINEAR_MIPMAP_LINEAR;
mag_filter = GL_NEAREST;
MipMap = GL_TRUE;
break;
default:
min_filter = GL_NEAREST;
mag_filter = GL_LINEAR;
}
if (!supportMipMap)
{
MipMap = GL_FALSE;
break;
case HWD_SET_TEXTUREFILTER_POINTSAMPLED:
min_filter = mag_filter = GL_NEAREST;
MipMap = GL_FALSE;
break;
case HWD_SET_TEXTUREFILTER_MIXED1:
min_filter = GL_NEAREST;
mag_filter = GL_LINEAR;
MipMap = GL_FALSE;
break;
case HWD_SET_TEXTUREFILTER_MIXED2:
min_filter = GL_LINEAR;
mag_filter = GL_NEAREST;
MipMap = GL_FALSE;
break;
case HWD_SET_TEXTUREFILTER_MIXED3:
min_filter = GL_LINEAR_MIPMAP_LINEAR;
mag_filter = GL_NEAREST;
MipMap = GL_TRUE;
break;
default:
min_filter = GL_NEAREST;
mag_filter = GL_LINEAR;
}
}
if (!supportMipMap)
{
MipMap = GL_FALSE;
min_filter = GL_LINEAR;
GL_Flush(); //??? if we want to change filter mode by texture, remove this
}
break;
GL_Flush(); //??? if we want to change filter mode by texture, remove this
case HWD_SET_WIREFRAME:
pglPolygonMode(GL_FRONT_AND_BACK, Value ? GL_LINE : GL_FILL);
break;
case HWD_SET_TEXTURE_FORMAT:
@@ -2699,7 +2739,7 @@ void GL_DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics
pglColor4ubv((GLubyte*)&Surface->PolyColor.s);
GL_SetBlend((poly.alpha < 1 ? Surface->PolyFlags : (PF_Masked|PF_Occlude))|PF_Modulated);
GL_SetBlend(((poly.alpha < 1) ? Surface->PolyFlags : (PF_Masked|PF_Occlude))|PF_Modulated);
tint.red = byte2float[Surface->TintColor.s.red];
tint.green = byte2float[Surface->TintColor.s.green];
@@ -2743,9 +2783,9 @@ void GL_DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics
if (hflipped)
scalez = -scalez;
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f);
pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f);
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f);
pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f);
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
if (pos->roll)
{
@@ -2916,8 +2956,10 @@ void GL_SetTransform(FTransform *stransform)
if (shearing)
{
float dy = stransform->viewaiming * 2;
if (stransform->fliptype == TRANSFORM_FLIP || stransform->fliptype == TRANSFORM_MIRRORFLIP)
dy *= -1.0f;
pglTranslatef(0.0f, -dy/BASEVIDHEIGHT, 0.0f);
}
@@ -2969,9 +3011,9 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
const float blackBack[16] =
{
-16.0f, -16.0f, 6.0f,
-16.0f, 16.0f, 6.0f,
16.0f, 16.0f, 6.0f,
16.0f, -16.0f, 6.0f
-16.0f, 16.0f, 6.0f,
16.0f, 16.0f, 6.0f,
16.0f, -16.0f, 6.0f
};
if (gl_enable_screen_textures != 2)
@@ -2993,9 +3035,9 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
pglEnableClientState(GL_TEXTURE_COORD_ARRAY);
for(x = 0; x < SCREENVERTS-1;x ++)
for (x = 0; x < (SCREENVERTS-1); x ++)
{
for(y = 0; y < SCREENVERTS-1; y++)
for (y = 0; y < (SCREENVERTS-1); y++)
{
float stCoords[8];
float vertCoords[12];
@@ -3047,23 +3089,22 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2])
void GL_FlushScreenTextures(void)
{
pglDeleteTextures(NUMSCREENTEXTURES, screenTextures);
memset(screenTextures, 0 , sizeof(screenTextures));
memset(screenTextures, 0, sizeof(screenTextures));
}
void GL_DrawScreenTexture(int tex, FSurfaceInfo *surf, FBITFIELD polyflags)
{
float fix[8];
float xfix, yfix;
const float screenVerts[12] =
{
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
float fix[8];
if (gl_enable_screen_textures != 2)
return;
@@ -3108,9 +3149,9 @@ void GL_DoScreenWipe(int wipeStart, int wipeEnd)
const float screenVerts[12] =
{
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
float fix[8];
@@ -3194,9 +3235,9 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8
float screenVerts[12] =
{
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f
};
if (gl_enable_screen_textures != 2)
@@ -3295,6 +3336,7 @@ void GL_MakeScreenTexture(int tex)
// Create screen texture
if (firstTime)
pglGenTextures(1, &screenTextures[tex]);
pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]);
if (firstTime)
@@ -3329,6 +3371,7 @@ void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height, boolean usesh
origaspect = (float)screen_width / screen_height;
newaspect = (float)width / height;
if (origaspect < newaspect)
{
xoff = origaspect / newaspect;
@@ -3464,8 +3507,10 @@ void GL_SetScreenPalette(RGBA_t *palette)
if (memcmp(screenPalette, palette, sizeof(screenPalette)))
{
memcpy(screenPalette, palette, sizeof(screenPalette));
if (!screenPaletteTex)
pglGenTextures(1, &screenPaletteTex);
pglActiveTexture(GL_TEXTURE2);
pglBindTexture(GL_TEXTURE_1D, screenPaletteTex);
pglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+4 -4
View File
@@ -220,9 +220,9 @@ HMS_connect (const char *format, ...)
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, (long)CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long)cv_masterserver_timeout.value);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, buffer);
@@ -339,8 +339,8 @@ HMS_unlist (void)
if (! hms)
return 0;
curl_easy_setopt(hms->curl, CURLOPT_POST, 1);
curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDSIZE, 0);
curl_easy_setopt(hms->curl, CURLOPT_POST, (long)1);
curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDSIZE, (long)0);
okay = HMS_do(hms);
HMS_end(hms);
+65 -4
View File
@@ -2133,7 +2133,7 @@ void HU_TickSongCredits(void)
}
}
void HU_DrawSongCredits(void)
static void HU_DrawSongCreditsVanilla(void)
{
char *str;
INT32 len;
@@ -2141,9 +2141,6 @@ void HU_DrawSongCredits(void)
INT32 y = (splitscreen ? (BASEVIDHEIGHT/2)-4 : 32);
INT32 bgt;
if (!cursongcredit.def) // No def
return;
str = va("\x1F"" %s", cursongcredit.def->source);
len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
destx = (len + 7) * FRACUNIT;
@@ -2173,6 +2170,70 @@ void HU_DrawSongCredits(void)
V_DrawRightAlignedThinString(cursongcredit.x / FRACUNIT, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
}
#define BOXCREDITSLIDEIN (5*TICRATE-TICRATE/2)
#define BOXCREDITSLIDEOUT (TICRATE/2)
#define BOXCREDITHEIGHT 8
static void HU_DrawSongCreditsBox(void)
{
char *str = cursongcredit.def->source;
INT32 strwidth = V_SmallStringWidth(str, V_ALLOWLOWERCASE) + 4;
// dup dup dup dup
INT32 dup = min(vid.dupx, vid.dupy);
// Center it
INT32 x = (BASEVIDWIDTH/2 - strwidth/2)*dup + ((vid.width - (BASEVIDWIDTH * vid.dupx)) / 2);
INT32 y = 0;
INT32 flags = V_SNAPTOTOP|V_NOSCALESTART;
INT32 t = cursongcredit.anim;
INT32 bgt;
fixed_t interpoffset = FixedMul(BOXCREDITHEIGHT*dup*FRACUNIT/(TICRATE/2), R_GetHudUncap());
if (t > BOXCREDITSLIDEIN)
{
// Sliding in
t = TICRATE/2 - (t - BOXCREDITSLIDEIN);
y = -BOXCREDITHEIGHT*dup + (FixedMul(BOXCREDITHEIGHT*FRACUNIT, FixedDiv(t*FRACUNIT, TICRATE*FRACUNIT/2))*dup + interpoffset)/FRACUNIT;
}
else if (t < TICRATE/2)
{
// Sliding out
y = -BOXCREDITHEIGHT*dup + (FixedMul(BOXCREDITHEIGHT*FRACUNIT, FixedDiv(t*FRACUNIT, TICRATE*FRACUNIT/2))*dup - interpoffset)/FRACUNIT;
}
bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans/2);
if (bgt < NUMTRANSMAPS)
{
V_DrawFill(x, y, strwidth*dup, BOXCREDITHEIGHT*dup, 28|flags|(bgt<<V_ALPHASHIFT));
V_DrawFill(x+dup, y+dup, (strwidth-2)*dup, (BOXCREDITHEIGHT-2)*dup, 30|flags|(bgt<<V_ALPHASHIFT));
}
if (cursongcredit.trans < NUMTRANSMAPS)
{
V_DrawSmallString(x+2*dup, y+2*dup, V_ALLOWLOWERCASE|flags|(cursongcredit.trans<<V_ALPHASHIFT), str);
}
}
void HU_DrawSongCredits(void)
{
if (!cursongcredit.def) // No def
return;
switch (cv_songcredits.value)
{
case 1:
HU_DrawSongCreditsVanilla();
break;
case 2:
HU_DrawSongCreditsBox();
break;
default:
break;
}
}
// Heads up displays drawer, call each frame
//
+8
View File
@@ -13,6 +13,10 @@
#ifndef __I_JOY_H__
#define __I_JOY_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "g_input.h"
/*!
@@ -55,4 +59,8 @@ typedef struct JoyType_s JoyType_t;
extern JoyType_t Joystick[MAXSPLITSCREENPLAYERS];
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __I_JOY_H__
+8
View File
@@ -14,6 +14,10 @@
#ifndef __I_NET__
#define __I_NET__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __GNUG__
#pragma interface
#endif
@@ -180,4 +184,8 @@ extern bannednode_t *bannednode;
/// \brief Called by D_SRB2Main to be defined by extern network driver
boolean I_InitNetwork(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+8
View File
@@ -13,6 +13,10 @@
#ifndef __I_SOUND__
#define __I_SOUND__
#ifdef __cplusplus
extern "C" {
#endif
#include "doomdef.h"
#include "sounds.h"
#include "command.h"
@@ -241,4 +245,8 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
boolean I_FadeOutStopSong(UINT32 ms);
boolean I_FadeInPlaySong(UINT32 ms, boolean looping);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+8
View File
@@ -14,6 +14,10 @@
#ifndef __I_SYSTEM__
#define __I_SYSTEM__
#ifdef __cplusplus
extern "C" {
#endif
#include "d_ticcmd.h"
#include "d_event.h"
@@ -256,4 +260,8 @@ const char *I_ClipboardPaste(void);
void I_RegisterSysCommands(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+8
View File
@@ -14,6 +14,10 @@
#ifndef I_THREADS_H
#define I_THREADS_H
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*I_thread_fn)(void *userdata);
typedef void * I_mutex;
@@ -35,5 +39,9 @@ void I_hold_cond (I_cond *, I_mutex);
void I_wake_one_cond (I_cond *);
void I_wake_all_cond (I_cond *);
#ifdef __cplusplus
} // extern "C"
#endif
#endif/*I_THREADS_H*/
#endif/*HAVE_THREADS*/
+10 -8
View File
@@ -37,18 +37,20 @@ tic_t I_GetTime(void)
void I_InitializeTime(void)
{
g_time.time = 0;
g_time.timefrac = 0;
enterprecise = 0;
oldenterprecise = 0;
tictimer = 0.0;
CV_RegisterVar(&cv_timescale);
// I_StartupTimer is preserved for potential subsystems that need to setup
// timing information for I_GetPreciseTime and sleeping
I_StartupTimer();
g_time.time = 0;
g_time.timefrac = 0;
enterprecise = I_GetPreciseTime();
oldenterprecise = enterprecise;
entertic = 0;
oldentertics = 0;
tictimer = 0.0;
}
void I_UpdateTime(fixed_t timescale)
@@ -61,7 +63,7 @@ void I_UpdateTime(fixed_t timescale)
ticratescaled = (double)TICRATE * FixedToFloat(timescale);
enterprecise = I_GetPreciseTime();
elapsedseconds = (double)((INT64)enterprecise - oldenterprecise) / I_GetPrecisePrecision();
elapsedseconds = (double)(enterprecise - oldenterprecise) / I_GetPrecisePrecision();
tictimer += elapsedseconds;
while (tictimer > 1.0/ticratescaled)
{
+8
View File
@@ -14,6 +14,10 @@
#ifndef __I_VIDEO__
#define __I_VIDEO__
#ifdef __cplusplus
extern "C" {
#endif
#include "doomtype.h"
#ifdef __GNUG__
@@ -149,4 +153,8 @@ boolean UseScreenFBO(void);
extern boolean downsample;
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+3 -2
View File
@@ -10525,11 +10525,12 @@ static void K_drawKartWanted(void)
{
INT32 x = basex+(splitscreen > 1 ? 13 : 8), y = basey+(splitscreen > 1 ? 16 : 21);
fixed_t scale = FRACUNIT/2;
player_t *p = &players[battlewanted[i]];
if (battlewanted[i] == -1)
break;
player_t *p = &players[battlewanted[i]];
if (numwanted == 1)
scale = FRACUNIT;
else
@@ -10540,7 +10541,7 @@ static void K_drawKartWanted(void)
y += 16;
}
if (players[battlewanted[i]].skincolor)
if (p->skincolor)
{
colormap = R_GetTranslationColormap(TC_RAINBOW, p->skincolor, GTC_CACHE);
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, V_HUDTRANS|(splitscreen < 3 ? V_SNAPTORIGHT : 0)|V_SNAPTOBOTTOM, (scale == FRACUNIT ? R_GetSkinFaceWant(p) : R_GetSkinFaceRank(p)), colormap);
+8
View File
@@ -6,6 +6,10 @@
#ifndef __K_KART__
#define __K_KART__
#ifdef __cplusplus
extern "C" {
#endif
#include "doomdef.h"
#include "d_player.h" // Need for player_t
@@ -132,5 +136,9 @@ INT32 K_getMinimapTrans(void);
void K_getLapsDrawinfo(drawinfo_t *out);
void K_getMinimapDrawinfo(drawinfo_t *out);
#ifdef __cplusplus
} // extern "C"
#endif
// =========================================================================
#endif // __K_KART__
+1
View File
@@ -16,6 +16,7 @@
#include "p_slopes.h" // P_GetZAt
#include "z_zone.h"
#include "r_main.h"
#include "r_skins.h"
#include "r_things.h"
#include "m_random.h"
#include "s_sound.h"
+1
View File
@@ -14,6 +14,7 @@
#include "doomstat.h"
#include "p_mobj.h"
#include "g_game.h"
#include "r_skins.h"
#include "r_things.h"
#include "b_bot.h"
#include "z_zone.h"
+1
View File
@@ -15,6 +15,7 @@
#include "doomdef.h"
#include "fastcmp.h"
#include "r_things.h"
#include "r_skins.h"
#include "r_main.h"
#include "p_local.h"
#include "g_game.h"
+1
View File
@@ -13,6 +13,7 @@
#include "doomdef.h"
#include "fastcmp.h"
#include "r_main.h"
#include "r_skins.h"
#include "r_things.h"
#include "p_mobj.h"
#include "d_player.h"
+2 -1
View File
@@ -12,6 +12,7 @@
#include "doomdef.h"
#include "fastcmp.h"
#include "r_skins.h"
#include "r_things.h"
#include "sounds.h"
@@ -277,4 +278,4 @@ int LUA_SkinLib(lua_State *L)
lua_setglobal(L, "skins");
return 0;
}
}
+4 -4
View File
@@ -495,7 +495,7 @@ static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr)
static void GIF_framewrite(void)
{
UINT8 *p;
UINT8 *movie_screen = screens[2];
UINT8 *movie_screen = vid.screens[2];
INT32 blitx, blity, blitw, blith;
if (!gifframe_data)
@@ -509,7 +509,7 @@ static void GIF_framewrite(void)
if (gif_optimize && gif_frames > 0)
{
// before blit movie_screen points to last frame, cur_screen points to this frame
UINT8 *cur_screen = screens[0];
UINT8 *cur_screen = vid.screens[0];
GIF_optimizeregion(cur_screen, movie_screen, &blitx, &blity, &blitw, &blith);
// blit to temp screen
@@ -535,7 +535,7 @@ static void GIF_framewrite(void)
if (rendermode == render_opengl)
{
UINT8 *linear = HWR_GetScreenshot();
GIF_rgbconvert(linear, screens[0]);
GIF_rgbconvert(linear, vid.screens[0]);
//free(linear); // Allocated 'statically', no need to free now
}
#endif
@@ -545,7 +545,7 @@ static void GIF_framewrite(void)
if (gif_frames == 0 && rendermode == render_soft)
I_ReadScreen(movie_screen);
movie_screen = screens[0];
movie_screen = vid.screens[0];
}
// screen regions are handled in GIF_lzw
+8
View File
@@ -14,6 +14,10 @@
#ifndef __M_ARGV__
#define __M_ARGV__
#ifdef __cplusplus
extern "C" {
#endif
//
// MISC
//
@@ -42,4 +46,8 @@ const char *M_GetNextParm(void);
// Finds and loads a response file (@moreargs.txt)
void M_FindResponseFile(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__M_ARGV__
+14
View File
@@ -49,6 +49,20 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f)
return (fixed_t)(f * FRACUNIT);
}
/*!
\brief convert fixed_t into double-precision floating number
*/
FUNCMATH FUNCINLINE static ATTRINLINE double FixedToDouble(fixed_t x)
{
return x / (double)FRACUNIT;
}
FUNCMATH FUNCINLINE static ATTRINLINE fixed_t DoubleToFixed(double f)
{
return (fixed_t)(f * FRACUNIT);
}
// for backwards compat
#define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT))
#define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT))
+79 -60
View File
@@ -2188,29 +2188,30 @@ static menuitem_t OP_SaturnMenu[] =
{IT_STRING | IT_CVAR, NULL, "Minimum Input Delay", &cv_mindelay, 20},
{IT_STRING | IT_CVAR, NULL, "Gentlemens Ping", &cv_gentlemens, 25},
{IT_STRING | IT_CVAR, NULL, "Server Info Screen", &cv_serverinfoscreen, 30},
{IT_STRING | IT_CVAR, NULL, "Skin Select Spinning Speed", &cv_skinselectspin, 35},
{IT_STRING | IT_CVAR, NULL, "Skin Select Spinning Speed", &cv_skinselectspin, 40},
{IT_STRING | IT_CVAR, NULL, "Colorized Speedlines", &cv_coloredspeedlines, 45},
{IT_STRING | IT_CVAR, NULL, "Colorized Sneakertrails", &cv_coloredsneakertrail, 50},
{IT_STRING | IT_CVAR, NULL, "Colorized Speedlines", &cv_coloredspeedlines, 50},
{IT_STRING | IT_CVAR, NULL, "Colorized Sneakertrails", &cv_coloredsneakertrail, 55},
{IT_STRING | IT_CVAR, NULL, "Player Blendeffects", &cv_playerblendeffects, 60},
{IT_STRING | IT_CVAR, NULL, "Player Blendeffects", &cv_playerblendeffects, 65},
{IT_STRING | IT_CVAR, NULL, "Bananadrag Jitter", &cv_bananajitter, 70},
{IT_STRING | IT_CVAR, NULL, "Bananadrag Jitter", &cv_bananajitter, 75},
{IT_STRING | IT_CVAR, NULL, "Midair Driftsparks", &cv_airsparks, 80},
{IT_STRING | IT_CVAR, NULL, "Midair Driftsparks", &cv_airsparks, 85},
{IT_STRING | IT_CVAR, NULL, "Show Localskin Menus", &cv_showlocalskinmenus, 90},
{IT_STRING | IT_CVAR, NULL, "Show Localskin Menus", &cv_showlocalskinmenus, 95},
{IT_STRING | IT_CVAR, NULL, "Uppercase Menu", &cv_menucaps, 100},
{IT_STRING | IT_CVAR, NULL, "Uppercase Menu", &cv_menucaps, 105},
{IT_STRING | IT_CVAR, NULL, "Keyboard Layout", &cv_keyboardlayout, 110},
{IT_STRING | IT_CVAR, NULL, "Keyboard Layout", &cv_keyboardlayout, 115},
{IT_STRING | IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 120},
{IT_STRING | IT_CVAR, NULL, "Less Midnight Channel Flicker", &cv_lessflicker, 125},
{IT_SUBMENU|IT_STRING, NULL, "Saturn Hud...", &OP_SaturnHudDef, 130},
{IT_SUBMENU|IT_STRING, NULL, "Sprite Distortion...", &OP_PlayerDistortDef, 135},
{IT_SUBMENU|IT_STRING, NULL, "Saturn Credits", &OP_SaturnCreditsDef, 140}, // uwu
{IT_SUBMENU|IT_STRING, NULL, "Saturn Hud...", &OP_SaturnHudDef, 135},
{IT_SUBMENU|IT_STRING, NULL, "Sprite Distortion...", &OP_PlayerDistortDef, 140},
{IT_SUBMENU|IT_STRING, NULL, "Saturn Credits", &OP_SaturnCreditsDef, 145}, // uwu
};
static const char* OP_SaturnTooltips[] =
@@ -2219,6 +2220,7 @@ static const char* OP_SaturnTooltips[] =
"How long can the game wait before it kicks you out from the server\nconnecting screen.",
"Practice for online play! 0 = instant response.",
"Simulate online input delay when hosting a server.\nValue choosen by Player with the lowest ping",
"Show a screen before joining a server displaying important information about it",
"How much speen do you want?",
"Colourize the speedlines in your skincolor if you go fast enough!",
"Colourize the sneaker flame trails in your skincolor!",
@@ -2466,39 +2468,38 @@ static menuitem_t OP_HudOffsetMenu[] =
static menuitem_t OP_SaturnCreditsMenu[] =
{
{IT_HEADER, NULL, "Saturn Credits", NULL, 0},
{IT_HEADER, NULL, "Thanks to all contributers <3", NULL, 0},
{IT_HEADER, NULL, "Thanks to all contributers <3", NULL, 7},
{IT_STRING2+IT_SPACE, NULL, "Alug", NULL, 10},
{IT_STRING2+IT_SPACE, NULL, "Indev", NULL, 20},
{IT_STRING2+IT_SPACE, NULL, "Haya", NULL, 30},
{IT_STRING2+IT_SPACE, NULL, "Nepdisk", NULL, 40},
{IT_STRING2+IT_SPACE, NULL, "GenericHeroGuy", NULL, 50},
{IT_STRING2+IT_SPACE, NULL, "xyzzy", NULL, 60},
{IT_STRING2+IT_SPACE, NULL, "Chearii", NULL, 70},
{IT_STRING2+IT_SPACE, NULL, "Alug", NULL, 17},
{IT_STRING2+IT_SPACE, NULL, "Indev", NULL, 27},
{IT_STRING2+IT_SPACE, NULL, "Haya", NULL, 37},
{IT_STRING2+IT_SPACE, NULL, "Nepdisk", NULL, 47},
{IT_STRING2+IT_SPACE, NULL, "GenericHeroGuy", NULL, 57},
{IT_STRING2+IT_SPACE, NULL, "xyzzy", NULL, 67},
{IT_STRING2+IT_SPACE, NULL, "Chearii", NULL, 77},
{IT_STRING2+IT_SPACE, NULL, "Sunflower", NULL, 80},
{IT_STRING2+IT_SPACE, NULL, "Yuz", NULL, 90},
{IT_STRING2+IT_SPACE, NULL, "Democrab", NULL, 100},
{IT_STRING2+IT_SPACE, NULL, "EXpand", NULL, 110},
{IT_STRING2+IT_SPACE, NULL, "Nexit", NULL, 120},
{IT_STRING2+IT_SPACE, NULL, "Spee", NULL, 130},
{IT_STRING2+IT_SPACE, NULL, "jin", NULL, 140},
{IT_STRING2+IT_SPACE, NULL, "riomccloud", NULL, 150},
{IT_STRING2+IT_SPACE, NULL, "chromaticpipe", NULL, 160},
{IT_STRING2+IT_SPACE, NULL, "Achii", NULL, 170},
{IT_STRING2+IT_SPACE, NULL, "Anonimus", NULL, 180},
{IT_STRING2+IT_SPACE, NULL, "scizor300", NULL, 190},
{IT_STRING2+IT_SPACE, NULL, "Lugent", NULL, 200},
{IT_STRING2+IT_SPACE, NULL, "Sunflower aka AnimeSonic", NULL, 87},
{IT_STRING2+IT_SPACE, NULL, "Yuz aka Yuzler", NULL, 97},
{IT_STRING2+IT_SPACE, NULL, "Democrab", NULL, 107},
{IT_STRING2+IT_SPACE, NULL, "EXpand", NULL, 117},
{IT_STRING2+IT_SPACE, NULL, "Nexit", NULL, 127},
{IT_STRING2+IT_SPACE, NULL, "Spee", NULL, 137},
{IT_STRING2+IT_SPACE, NULL, "jin", NULL, 147},
{IT_STRING2+IT_SPACE, NULL, "riomccloud", NULL, 157},
{IT_STRING2+IT_SPACE, NULL, "chromaticpipe", NULL, 167},
{IT_STRING2+IT_SPACE, NULL, "Achii", NULL, 177},
{IT_STRING2+IT_SPACE, NULL, "Anonimus", NULL, 187},
{IT_STRING2+IT_SPACE, NULL, "scizor300", NULL, 197},
{IT_HEADER, NULL, "Special Thanks <3", NULL, 168},
{IT_HEADER, NULL, "Special Thanks <3", NULL, 167},
{IT_STRING2+IT_SPACE, NULL, "All of Sunflower's Garden", NULL, 178},
{IT_STRING2+IT_SPACE, NULL, "The Moe Mansion and Birdhouse Team", NULL, 188},
{IT_STRING2+IT_SPACE, NULL, "Galactice for Galaxy", NULL, 198},
{IT_STRING2+IT_SPACE, NULL, "All of Sunflower's Garden", NULL, 177},
{IT_STRING2+IT_SPACE, NULL, "The Moe Mansion and Birdhouse Team", NULL, 187},
{IT_STRING2+IT_SPACE, NULL, "Galactice for Galaxy", NULL, 197},
{IT_STRING+IT_SPACE, NULL, "", NULL, 207}, // dummy text I
{IT_STRING, NULL, "", NULL, 267}, // dummy text II
{IT_STRING+IT_SPACE, NULL, "", NULL, 198}, // dummy text I
{IT_STRING, NULL, "", NULL, 258}, // dummy text II
};
// sry we dont have space for this anymore :/
@@ -3600,8 +3601,8 @@ static void M_ChangeCvar(INT32 choice)
char s[20];
float increment;
increment = (currentMenu->menuitems[itemOn].status & IT_CV_BIGFLOAT) ? 0.5f : (1.0f/16.0f);
sprintf(s, "%f",FIXED_TO_FLOAT(cv->value)+(choice)*increment);
increment = FIXED_TO_FLOAT(cv->value)+(choice)*((currentMenu->menuitems[itemOn].status & IT_CV_BIGFLOAT) ? 0.5f : (1.0f/16.0f));
sprintf(s,"%ld%s",(long)increment,M_Ftrim(increment));
CV_Set(cv, s);
}
else
@@ -7167,8 +7168,11 @@ static void DrawReplayHutReplayInfo(void)
if (mapheaderinfo[demolist[dir_on[menudepthleft]].map-1])
{
char *title = G_BuildMapTitle(demolist[dir_on[menudepthleft]].map);
V_DrawString(x, y, V_SNAPTOTOP|MENUCAPS, title);
Z_Free(title);
if (title)
{
V_DrawString(x, y, V_SNAPTOTOP|MENUCAPS, title);
Z_Free(title);
}
}
else
V_DrawString(x, y, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT, "Level is not loaded.");
@@ -8120,6 +8124,9 @@ UINT8 skyRoomMenuTranslations[MAXUNLOCKABLES];
static char *M_GetConditionString(condition_t cond)
{
char *title = NULL;
char *response = NULL;
switch(cond.type)
{
case UC_PLAYTIME:
@@ -8146,33 +8153,45 @@ static char *M_GetConditionString(condition_t cond)
G_TicsToSeconds(cond.requirement));
case UC_MAPVISITED:
{
char *title = G_BuildMapTitle(cond.requirement-1);
char *response = va("Visit %s", title);
Z_Free(title);
title = G_BuildMapTitle(cond.requirement-1);
if (title)
{
response = va("Visit %s", title);
Z_Free(title);
}
return response;
}
case UC_MAPBEATEN:
{
char *title = G_BuildMapTitle(cond.requirement-1);
char *response = va("Beat %s", title);
Z_Free(title);
title = G_BuildMapTitle(cond.requirement-1);
if (title)
{
response = va("Beat %s", title);
Z_Free(title);
}
return response;
}
case UC_MAPALLEMERALDS:
{
char *title = G_BuildMapTitle(cond.requirement-1);
char *response = va("Beat %s w/ all emeralds", title);
Z_Free(title);
title = G_BuildMapTitle(cond.requirement-1);
if (title)
{
response = va("Beat %s w/ all emeralds", title);
Z_Free(title);
}
return response;
}
case UC_MAPTIME:
{
char *title = G_BuildMapTitle(cond.extrainfo1-1);
char *response = va("Beat %s in %i:%02i.%02i", title,
G_TicsToMinutes(cond.requirement, true),
G_TicsToSeconds(cond.requirement),
G_TicsToCentiseconds(cond.requirement));
Z_Free(title);
title = G_BuildMapTitle(cond.extrainfo1-1);
if (title)
{
response = va("Beat %s in %i:%02i.%02i", title,
G_TicsToMinutes(cond.requirement, true),
G_TicsToSeconds(cond.requirement),
G_TicsToCentiseconds(cond.requirement));
Z_Free(title);
}
return response;
}
case UC_TOTALEMBLEMS:
+9
View File
@@ -15,6 +15,11 @@
#ifndef __X_MENU__
#define __X_MENU__
#ifdef __cplusplus
extern "C" {
#endif
#include "r_skins.h"
#include "d_event.h"
#include "command.h"
#include "i_threads.h"
@@ -433,4 +438,8 @@ if (currentMenu == &menu)\
}\
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__X_MENU__
+32 -4
View File
@@ -14,6 +14,10 @@
#ifdef __GNUC__
#ifdef __cplusplus
extern "C" {
#endif
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
// Ignore "argument might be clobbered by longjmp" warning in GCC
// (if libpng is compiled with setjmp error handling)
@@ -1060,7 +1064,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
png_init_io(apng_ptr, apng_FILE);
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
png_set_user_limits(apng_ptr, MAXPNGWIDTH, MAXPNGHEIGHT);
png_set_user_limits(apng_ptr, MAXVIDWIDTH, MAXVIDHEIGHT);
#endif
//png_set_filter(apng_ptr, 0, PNG_ALL_FILTERS);
@@ -1237,7 +1241,7 @@ void M_SaveFrame(void)
if (rendermode == render_soft)
{
// munge planar buffer to linear
linear = screens[2];
linear = vid.screens[2];
I_ReadScreen(linear);
}
#ifdef HWRENDER
@@ -1375,7 +1379,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const
png_init_io(png_ptr, png_FILE);
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
png_set_user_limits(png_ptr, MAXPNGWIDTH, MAXPNGHEIGHT);
png_set_user_limits(png_ptr, MAXVIDWIDTH, MAXVIDHEIGHT);
#endif
//png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
@@ -1539,7 +1543,7 @@ void M_DoScreenShot(void)
if (rendermode == render_soft)
{
// munge planar buffer to linear
linear = screens[2];
linear = vid.screens[2];
I_ReadScreen(linear);
}
@@ -1966,6 +1970,25 @@ char *M_GetToken(const char *inputString)
return texturesToken;
}
const char * M_Ftrim (double f)
{
static char dig[9];/* "0." + 6 digits (6 is printf's default) */
int i;
/* I know I said it's the default, but just in case... */
sprintf(dig, "%.6f", fabs(modf(f, &f)));
/* trim trailing zeroes */
for (i = strlen(dig)-1; dig[i] == '0'; --i)
;
if (dig[i] == '.')/* :NOTHING: */
return "";
else
{
dig[i + 1] = '\0';
return &dig[1];/* skip the 0 */
}
}
/** Count bits in a number.
*/
UINT8 M_CountBits(UINT32 num, UINT8 size)
@@ -2191,3 +2214,8 @@ void M_MkdirEach(const char *path, int start, int mode)
{
M_MkdirEachUntil(path, start, -1, mode);
}
#ifdef __cplusplus
} // extern "C"
#endif
+14
View File
@@ -15,6 +15,10 @@
#ifndef __M_MISC__
#define __M_MISC__
#ifdef __cplusplus
extern "C" {
#endif
#include "doomtype.h"
#include "tables.h"
@@ -104,10 +108,20 @@ boolean M_IsPathAbsolute (const char *path);
void M_MkdirEach (const char *path, int start, int mode);
void M_MkdirEachUntil (const char *path, int start, int end, int mode);
/*
Return dot and then the fractional part of a float, without
trailing zeros, or "" if the fractional part is zero.
*/
const char * M_Ftrim (double);
// counting bits, for weapon ammo code, usually
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
#include "w_wad.h"
extern char configfile[MAX_WADPATH];
#ifdef __cplusplus
} // extern "C"
#endif
#endif
-6
View File
@@ -26,12 +26,6 @@
#if defined (STDC_HEADERS) || defined (_LIBC)
#include <stdlib.h>
#else
#ifndef HAVE_MEMCPY
#if !(defined (_WIN32) && !defined (__CYGWIN__)) && !defined (__APPLE__)
#define memcpy(d, s, n) bcopy ((s), (d), (n))
#endif
#endif
#endif
#include "md5.h"
+1
View File
@@ -16,6 +16,7 @@
#include "g_game.h"
#include "p_local.h"
#include "r_main.h"
#include "r_skins.h"
#include "r_state.h"
#include "s_sound.h"
#include "m_random.h"
+1
View File
@@ -20,6 +20,7 @@
#include "p_setup.h"
#include "r_fps.h"
#include "r_main.h"
#include "r_skins.h"
#include "r_things.h"
#include "r_sky.h"
#include "r_splats.h"
+9
View File
@@ -14,6 +14,10 @@
#ifndef __P_MOBJ__
#define __P_MOBJ__
#ifdef __cplusplus
extern "C" {
#endif
// Basics.
#include "tables.h"
#include "m_fixed.h"
@@ -536,4 +540,9 @@ extern mapthing_t *huntemeralds[MAXHUNTEMERALDS];
extern INT32 numhuntemeralds;
extern boolean runemeraldmanager;
extern INT32 numstarposts;
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+1
View File
@@ -24,6 +24,7 @@
#include "r_fps.h"
#include "r_things.h"
#include "r_state.h"
#include "r_skins.h"
#include "w_wad.h"
#include "y_inter.h"
#include "z_zone.h"
+32 -10
View File
@@ -580,9 +580,6 @@ static void P_LoadRawSegs(UINT8 *data)
else
li->backsector = 0;
li->numlights = 0;
li->rlights = NULL;
P_UpdateSegLightOffset(li);
}
}
@@ -675,6 +672,21 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
levelflat->lumpnum = R_GetFlatNumForName(flatname);
levelflat->baselumpnum = LUMPERROR;
// check if our flat contains cyan pixels
// not sure if this is the best way to do it but it works
{
const UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL);
size_t size = W_LumpLength(levelflat->lumpnum);
for (size_t steppy = 0; steppy < size; steppy++)
{
if (flat[steppy] == TRANSPARENTPIXEL)
{
levelflat->cyan = true;
break;
}
}
}
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
#endif
@@ -720,6 +732,21 @@ INT32 P_AddLevelFlatRuntime(const char *flatname)
levelflat->lumpnum = R_GetFlatNumForName(flatname);
levelflat->baselumpnum = LUMPERROR;
// check if our flat contains cyan pixels
// not sure if this is the best way to do it but it works
{
const UINT8 *flat = (UINT8 *)W_CacheLumpNum(levelflat->lumpnum, PU_LEVEL);
size_t size = W_LumpLength(levelflat->lumpnum);
for (size_t steppy = 0; steppy < size; steppy++)
{
if (flat[steppy] == TRANSPARENTPIXEL)
{
levelflat->cyan = true;
break;
}
}
}
#ifndef ZDEBUG
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
#endif
@@ -2747,8 +2774,6 @@ static void P_SetupPlayer(void)
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"online", srb2home), 0755);
G_RecordDemo(buf);
if (dedicated)
G_BeginRecording(); //this has to move here, since dedicated servers dont run got_mapcmd
}
wantedcalcdelay = wantedfrequency*2;
@@ -2868,12 +2893,9 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
F_WipeStartScreen();
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol);
F_WipeEndScreen();
F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
}
else //dedicated servers
{
F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
}
F_RunWipe(wipedefs[(encoremode ? wipe_level_final : wipe_level_toblack)], false);
}
// Reset the palette now all fades have been done
+9
View File
@@ -14,6 +14,10 @@
#ifndef __P_SETUP__
#define __P_SETUP__
#ifdef __cplusplus
extern "C" {
#endif
#include "doomdata.h"
#include "doomstat.h"
#include "r_defs.h"
@@ -48,6 +52,7 @@ typedef struct
INT32 animseq; // start pos. in the anim sequence
INT32 numpics;
INT32 speed;
boolean cyan;
} levelflat_t;
extern size_t numlevelflats;
@@ -116,4 +121,8 @@ UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare);
UINT8 P_HasGrades(INT16 map, UINT8 mare);
UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+1
View File
@@ -654,6 +654,7 @@ void P_Ticker(boolean run)
{
P_MapStart();
R_UpdateMobjInterpolators();
R_UpdateLevelInterpolators();
OP_ObjectplaceMovement(&players[0]);
P_MoveChaseCamera(&players[0], &camera[0], false);
R_UpdateViewInterpolation();
+9
View File
@@ -16,6 +16,15 @@
#ifndef __QS22J__
#define __QS22J__
#ifdef __cplusplus
extern "C" {
#endif
void qs22j(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+123 -189
View File
@@ -35,6 +35,7 @@ sector_t *backsector;
// very ugly realloc() of drawsegs at run-time, I upped it to 512
// instead of 256.. and someone managed to send me a level with
// 896 drawsegs! So too bad here's a limit removal a-la-Boom
drawseg_t *curdrawsegs = NULL; /**< This is used to handle multiple lists for masked drawsegs. */
drawseg_t *drawsegs = NULL;
drawseg_t *ds_p = NULL;
@@ -73,165 +74,96 @@ void R_ClearDrawSegs(void)
ds_p = drawsegs;
}
// Fix from boom.
#define MAXSEGS (MAXVIDWIDTH/2+1)
// CPhipps -
// Instead of clipsegs, let's try using an array with one entry for each column,
// indicating whether it's blocked by a solid wall yet or not.
UINT8 *solidcol;
// newend is one past the last valid seg
static cliprange_t *newend;
static cliprange_t solidsegs[MAXSEGS];
//
// R_ClipSolidWallSegment
// Does handle solid walls,
// e.g. single sided LineDefs (middle texture)
// that entirely block the view.
//
static void R_ClipSolidWallSegment(INT32 first, INT32 last)
void R_AllocClipSegMemory(void)
{
cliprange_t *next;
cliprange_t *start;
solidcol = static_cast<UINT8*>(Z_Realloc(solidcol, sizeof(*solidcol) * viewwidth, PU_STATIC, NULL));
}
// Find the first range that touches the range (adjacent pixels are touching).
start = solidsegs;
while (start->last < first - 1)
start++;
namespace
{
if (first < start->first)
enum class ClipType
{
// Does handle solid walls,
// e.g. single sided LineDefs (middle texture)
// that entirely block the view.
kSolid,
kSolidDontRender,
// Clips the given range of columns, but does not include it in the clip list.
// Does handle windows, e.g. LineDefs with upper and lower texture.
kPass,
};
// CPhipps -
// R_ClipWallSegment
//
// Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those
// columns which aren't solid, and updates the solidcol[] array appropriately
template <ClipType Type>
static void R_ClipWallSegment(int first, int last)
{
while (first < last)
{
if (last < start->first - 1)
{
// Post is entirely visible (above start), so insert a new clippost.
R_StoreWallRange(first, last);
next = newend;
newend++;
// NO MORE CRASHING!
if (newend - solidsegs > MAXSEGS)
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
UINT8 *p;
while (next != start)
if (solidcol[first])
{
p = static_cast<UINT8*>(memchr(solidcol+first, 0, last-first));
if (!p)
return; // All solid
first = p - solidcol;
}
else
{
p = static_cast<UINT8*>(memchr(solidcol+first, 1, last-first));
int to;
if (!p)
to = last;
else
to = p - solidcol;
if constexpr (Type != ClipType::kSolidDontRender)
{
*next = *(next-1);
next--;
R_StoreWallRange(first, to-1);
}
next->first = first;
next->last = last;
return;
}
// There is a fragment above *start.
R_StoreWallRange(first, start->first - 1);
// Now adjust the clip size.
start->first = first;
}
if constexpr (Type != ClipType::kPass)
{
memset(solidcol+first, 1, to-first);
}
// Bottom contained in start?
if (last <= start->last)
return;
next = start;
while (last >= (next+1)->first - 1)
{
// There is a fragment between two posts.
R_StoreWallRange(next->last + 1, (next+1)->first - 1);
next++;
if (last <= next->last)
{
// Bottom is contained in next.
// Adjust the clip size.
start->last = next->last;
goto crunch;
first = to;
}
}
// There is a fragment after *next.
R_StoreWallRange(next->last + 1, last);
// Adjust the clip size.
start->last = last;
// Remove start+1 to next from the clip list, because start now covers their area.
crunch:
if (next == start)
return; // Post just extended past the bottom of one post.
while (next++ != newend)
*++start = *next; // Remove a post.
newend = start + 1;
// NO MORE CRASHING!
if (newend - solidsegs > MAXSEGS)
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
}
//
// R_ClipPassWallSegment
// Clips the given range of columns, but does not include it in the clip list.
// Does handle windows, e.g. LineDefs with upper and lower texture.
//
static inline void R_ClipPassWallSegment(INT32 first, INT32 last, boolean soliddontrender)
{
cliprange_t *start;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = solidsegs;
while (start->last < first - 1)
start++;
if (first < start->first)
{
if (last < start->first - 1)
{
// Post is entirely visible (above start).
if (!soliddontrender)
R_StoreWallRange(first, last);
return;
}
// There is a fragment above *start.
if (!soliddontrender)
R_StoreWallRange(first, start->first - 1);
}
// Bottom contained in start?
if (last <= start->last)
return;
while (last >= (start+1)->first - 1)
{
// There is a fragment between two posts.
if (!soliddontrender)
R_StoreWallRange(start->last + 1, (start+1)->first - 1);
start++;
if (last <= start->last)
return;
}
// There is a fragment after *next.
if (!soliddontrender)
R_StoreWallRange(start->last + 1, last);
}
}; // namespace
//
// R_ClearClipSegs
//
void R_ClearClipSegs(void)
{
solidsegs[0].first = -0x7fffffff;
solidsegs[0].last = -1;
solidsegs[1].first = viewwidth;
solidsegs[1].last = 0x7fffffff;
newend = solidsegs + 2;
memset(solidcol, 0, viewwidth);
}
void R_PortalClearClipSegs(INT32 start, INT32 end)
{
solidsegs[0].first = -0x7fffffff;
solidsegs[0].last = start-1;
solidsegs[1].first = end;
solidsegs[1].last = 0x7fffffff;
newend = solidsegs + 2;
R_ClearClipSegs();
if (start > 0)
memset(solidcol, 1, start);
if (end < viewwidth)
memset(solidcol + end, 1, viewwidth - end);
}
//
@@ -389,6 +321,7 @@ static void R_AddLine(seg_t *line)
INT32 x1, x2;
angle_t angle1, angle2, span, tspan;
static sector_t tempsec;
boolean bothfloorssky = false;
g_portal = NULL;
@@ -405,7 +338,7 @@ static void R_AddLine(seg_t *line)
span = angle1 - angle2;
// Back side? i.e. backface culling?
if (span >= ANGLE_180 || !line->linedef)
if (span >= ANGLE_180)
return;
// Global angle needed by segcalc.
@@ -424,6 +357,7 @@ static void R_AddLine(seg_t *line)
angle1 = clipangle;
}
tspan = clipangle - angle2;
if (tspan > doubleclipangle)
{
@@ -439,6 +373,8 @@ static void R_AddLine(seg_t *line)
// The seg is in the view range, but not necessarily visible.
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT;
// killough 1/31/98: Here is where "slime trails" can SOMETIMES occur:
x1 = viewangletox[angle1];
x2 = viewangletox[angle2];
@@ -455,8 +391,10 @@ static void R_AddLine(seg_t *line)
{
// Find the other side!
INT32 line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, -1);
if (line->linedef == &lines[line2])
line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2);
if (line2 >= 0) // found it!
{
Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering
@@ -476,6 +414,10 @@ static void R_AddLine(seg_t *line)
doorclosed = 0;
// likewise, but for floors and upper textures
if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum)
bothfloorssky = true;
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
@@ -503,19 +445,19 @@ static void R_AddLine(seg_t *line)
if (viewsector != backsector && viewsector != frontsector)
{
// here we're talking about a CEILING lower than a floor. ...yeah we don't even need to bother.
if (backc1 <= frontf1 && backc2 <= frontf2)
const boolean ceillow = (backc1 <= frontf1 && backc2 <= frontf2);
// this tries to fix some skyboxes drawing a black void as a midtexture lel
if (ceillow && (!bothfloorssky && backsector->ceilingpic == skyflatnum && frontsector->ceilingpic != skyflatnum) // double sided with back ceiling sky but not front ceiling sky
&& !line->sidedef->midtexture && !line->sidedef->bottomtexture && !line->sidedef->toptexture && !line->polyseg) // effectively empty
{
goto clipsolid;
}
// here we're talking about floors higher than ceilings, don't even bother either.
if (backf1 >= frontc1 && backf2 >= frontc2)
{
goto clipsolid;
goto clippass;
}
doorclosed = ceillow
|| (backf1 >= frontc1 && backf2 >= frontc2)
// Check for automap fix. Store in doorclosed for r_segs.c
doorclosed = (backc1 <= backf1 && backc2 <= backf2
|| (backc1 <= backf1 && backc2 <= backf2
&& ((backc1 >= frontc1 && backc2 >= frontc2) || curline->sidedef->toptexture)
&& ((backf1 <= frontf1 && backf2 >= frontf2) || curline->sidedef->bottomtexture)
&& (backsector->ceilingpic != skyflatnum || frontsector->ceilingpic != skyflatnum));
@@ -540,15 +482,15 @@ static void R_AddLine(seg_t *line)
clippass:
g_walloffscreen = false;
R_ClipPassWallSegment(x1, x2 - 1, false);
R_ClipWallSegment<ClipType::kPass>(x1, x2);
if (g_walloffscreen)
R_ClipPassWallSegment(x1, x2 - 1, true);
R_ClipWallSegment<ClipType::kSolidDontRender>(x1, x2);
return;
clipsolid:
g_walloffscreen = false;
R_ClipSolidWallSegment(x1, x2 - 1);
R_ClipWallSegment<ClipType::kSolid>(x1, x2);
}
//
@@ -581,22 +523,11 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
angle_t angle1, angle2;
INT32 sx1, sx2, boxpos;
const INT32* check;
cliprange_t *start;
// Find the corners of the box that define the edges from current viewpoint.
if (viewx <= bspcoord[BOXLEFT])
boxpos = 0;
else if (viewx < bspcoord[BOXRIGHT])
boxpos = 1;
else
boxpos = 2;
if (viewy >= bspcoord[BOXTOP])
boxpos |= 0;
else if (viewy > bspcoord[BOXBOTTOM])
boxpos |= 1<<2;
else
boxpos |= 2<<2;
// Find the corners of the box
// that define the edges from current viewpoint.
boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT ] ? 1 : 2) +
(viewy >= bspcoord[BOXTOP ] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8);
if (boxpos == 5)
return true;
@@ -607,18 +538,23 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
angle1 = R_PointToAngle64(bspcoord[check[0]], bspcoord[check[1]]) - viewangle;
angle2 = R_PointToAngle64(bspcoord[check[2]], bspcoord[check[3]]) - viewangle;
if ((signed)angle1 < (signed)angle2)
// cph - replaced old code, which was unclear and badly commented
// Much more efficient code now
if ((signed)angle1 < (signed)angle2) /* it's "behind" us */
{
/* Either angle1 or angle2 is behind us, so it doesn't matter if we
* change it to the corect sign
*/
if ((angle1 >= ANGLE_180) && (angle1 < ANGLE_270))
angle1 = ANGLE_180-1;
else
angle2 = ANGLE_180;
}
if ((signed)angle2 >= (signed)clipangle) return false;
if ((signed)angle1 <= -(signed)clipangle) return false;
if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle;
if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle;
if ((signed)angle2 >= (signed)clipangle) return false; // Both off left edge
if ((signed)angle1 <= -(signed)clipangle) return false; // Both off right edge
if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle; // Clip at left edge
if ((signed)angle2 <= -(signed)clipangle) angle2 = -(signed)clipangle; // Clip at right edge
// Find the first clippost that touches the source post (adjacent pixels are touching).
angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT;
@@ -630,20 +566,18 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
if (sx1 >= sx2)
return false;
start = solidsegs;
while (start->last < sx2)
start++;
if (sx1 >= start->first && sx2 <= start->last)
return false; // The clippost contains the new span.
if (!memchr(solidcol+sx1, 0, sx2-sx1))
{
// All columns it covers are already solidly covered
return false;
}
return true;
}
size_t numpolys; // number of polyobjects in current subsector
size_t num_po_ptrs; // number of polyobject pointers allocated
polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
//
// R_PolyobjCompare
@@ -681,8 +615,7 @@ void R_SortPolyObjects(subsector_t *sub)
{
// use free instead realloc since faster (thanks Lee ^_^)
free(po_ptrs);
po_ptrs = malloc((num_po_ptrs = numpolys*2)
* sizeof(*po_ptrs));
po_ptrs = static_cast<polyobj_t**>(malloc((num_po_ptrs = numpolys*2)* sizeof(*po_ptrs)));
}
po = sub->polyList;
@@ -699,8 +632,7 @@ void R_SortPolyObjects(subsector_t *sub)
// 03/10/06: only bother if there are actually polys to sort
if (numpolys >= 2)
{
qs22j(po_ptrs, numpolys, sizeof(polyobj_t *),
R_PolyobjCompare);
qs22j(po_ptrs, numpolys, sizeof(polyobj_t *), R_PolyobjCompare);
}
}
}
@@ -726,8 +658,8 @@ static int R_PolysegCompare(const void *p1, const void *p2)
dist2v1 = vxdist(seg2->v1);
dist2v2 = vxdist(seg2->v2);
if (min(dist1v1, dist1v2) != min(dist2v1, dist2v2))
return min(dist1v1, dist1v2) - min(dist2v1, dist2v2);
if (std::min(dist1v1, dist1v2) != std::min(dist2v1, dist2v2))
return std::min(dist1v1, dist1v2) - std::min(dist2v1, dist2v2);
{ // That didn't work, so now let's try this.......
fixed_t delta1, delta2, x1, y1, x2, y2;
@@ -828,14 +760,15 @@ static void R_Subsector(size_t num)
fixed_t floorcenterz, ceilingcenterz;
ffloor_t *rover;
#ifdef RANGECHECK
if (num >= numsubsectors)
I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
#endif
// subsectors added at run-time
if (num >= numsubsectors)
{
#ifdef RANGECHECK
I_Error("R_Subsector: ss %s with numss = %s\n", sizeu1(num), sizeu2(numsubsectors));
#else
return;
#endif
}
sub = &subsectors[num];
frontsector = sub->sector;
@@ -1144,7 +1077,7 @@ void R_Prep3DFloors(sector_t *sector)
if (count != sector->numlights)
{
Z_Free(sector->lightlist);
sector->lightlist = Z_Calloc(sizeof (*sector->lightlist) * count, PU_LEVEL, NULL);
sector->lightlist = static_cast<lightlist_t*>(Z_Calloc(sizeof (*sector->lightlist) * count, PU_LEVEL, NULL));
sector->numlights = count;
}
else
@@ -1194,6 +1127,7 @@ void R_Prep3DFloors(sector_t *sector)
}
}
}
if (!best)
{
sector->numlights = i;
+12
View File
@@ -14,6 +14,10 @@
#ifndef __R_BSP__
#define __R_BSP__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __GNUG__
#pragma interface
#endif
@@ -32,14 +36,17 @@ extern portal_t *g_portal; // is curline a portal seg?
extern INT32 checkcoord[12][4];
extern drawseg_t *curdrawsegs;
extern drawseg_t *drawsegs;
extern drawseg_t *ds_p;
extern INT32 doorclosed;
extern UINT8 *solidcol;
extern boolean g_walloffscreen;
// BSP?
void R_ClearClipSegs(void);
void R_PortalClearClipSegs(INT32 start, INT32 end);
void R_AllocClipSegMemory(void);
void R_ClearDrawSegs(void);
void R_RenderBSPNode(INT32 bspnum);
@@ -59,4 +66,9 @@ boolean R_IsEmptyLine(seg_t *line, const sector_t *front, const sector_t *back);
INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside);
void R_Prep3DFloors(sector_t *sector);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+23 -8
View File
@@ -100,7 +100,7 @@ INT32 numtextures = 0; // total number of textures found,
texture_t **textures = NULL;
static UINT32 **texturecolumnofs; // column offset lookup table for each texture
static UINT8 **texturecache; // graphics data for each generated full-size texture
UINT8 **texturecache; // graphics data for each generated full-size texture
// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask
INT32 *texturewidthmask;
@@ -296,7 +296,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig
// This is not optimised, but it's supposed to be executed only once
// per level, when enough memory is available.
//
static UINT8 *R_GenerateTexture(size_t texnum)
UINT8 *R_GenerateTexture(size_t texnum)
{
UINT8 *block;
UINT8 *blocktex;
@@ -649,6 +649,7 @@ void R_LoadTextures(void)
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
texture->width = SHORT(patchlump->width);
texture->height = SHORT(patchlump->height);
texture->type = TEXTURETYPE_SINGLEPATCH;
texture->patchcount = 1;
texture->holes = false;
@@ -690,12 +691,15 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
// Patch identifier
texturesToken = M_GetToken(NULL);
if (texturesToken == NULL)
{
I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch name should be");
}
texturesTokenLength = strlen(texturesToken);
if (texturesTokenLength>8)
if (texturesTokenLength > 8)
{
I_Error("Error parsing TEXTURES lump: Patch name \"%s\" exceeds 8 characters",texturesToken);
}
@@ -713,10 +717,12 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
// Comma 1
Z_Free(texturesToken);
texturesToken = M_GetToken(NULL);
if (texturesToken == NULL)
{
I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after \"%s\"'s patch name should be",patchName);
}
if (strcmp(texturesToken,",")!=0)
{
I_Error("Error parsing TEXTURES lump: Expected \",\" after %s's patch name, got \"%s\"",patchName,texturesToken);
@@ -725,14 +731,17 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
// XPos
Z_Free(texturesToken);
texturesToken = M_GetToken(NULL);
if (texturesToken == NULL)
{
I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s x coordinate should be",patchName);
}
endPos = NULL;
#ifndef AVOID_ERRNO
errno = 0;
#endif
patchXPos = strtol(texturesToken,&endPos,10);
(void)patchXPos; //unused for now
if (endPos == texturesToken // Empty string
@@ -748,10 +757,12 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
// Comma 2
Z_Free(texturesToken);
texturesToken = M_GetToken(NULL);
if (texturesToken == NULL)
{
I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after patch \"%s\"'s x coordinate should be",patchName);
}
if (strcmp(texturesToken,",")!=0)
{
I_Error("Error parsing TEXTURES lump: Expected \",\" after patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken);
@@ -760,6 +771,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
// YPos
Z_Free(texturesToken);
texturesToken = M_GetToken(NULL);
if (texturesToken == NULL)
{
I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s y coordinate should be",patchName);
@@ -904,19 +916,22 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture)
// Left Curly Brace
texturesToken = M_GetToken(NULL);
if (texturesToken == NULL)
{
I_Error("Error parsing TEXTURES lump: Unexpected end of file where open curly brace for texture \"%s\" should be",newTextureName);
}
if (strcmp(texturesToken,"{")==0)
{
if (actuallyLoadTexture)
{
// Allocate memory for a zero-patch texture. Obviously, we'll be adding patches momentarily.
resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t),PU_STATIC,NULL);
resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t), PU_STATIC, NULL);
M_Memcpy(resultTexture->name, newTextureName, 8);
resultTexture->width = newTextureWidth;
resultTexture->height = newTextureHeight;
resultTexture->type = TEXTURETYPE_COMPOSITE;
}
Z_Free(texturesToken);
texturesToken = M_GetToken(NULL);
@@ -1131,9 +1146,9 @@ static void R_InitExtraColormaps(void)
lumpnum_t R_GetFlatNumForName(const char *name)
{
INT32 i;
lumpnum_t lump;
lumpnum_t start;
lumpnum_t end;
lumpnum_t lump = LUMPERROR;
lumpnum_t start = LUMPERROR;
lumpnum_t end = LUMPERROR;
// Scan wad files backwards so patched flats take preference.
for (i = numwadfiles - 1; i >= 0; i--)
@@ -1608,7 +1623,7 @@ const char *R_ColormapNameForNum(INT32 num)
if (num == -1)
return "NONE";
if (num < 0 || num > MAXCOLORMAPS)
if (num < 0 || num >= MAXCOLORMAPS)
I_Error("R_ColormapNameForNum: num %d is invalid!\n", num);
if (foundcolormaps[num] == LUMPERROR)
+20
View File
@@ -14,6 +14,10 @@
#ifndef __R_DATA__
#define __R_DATA__
#ifdef __cplusplus
extern "C" {
#endif
#include "r_defs.h"
#include "r_state.h"
@@ -33,6 +37,14 @@ typedef struct
UINT16 wad, lump;
} texpatch_t;
// texture type
enum
{
TEXTURETYPE_UNKNOWN,
TEXTURETYPE_SINGLEPATCH,
TEXTURETYPE_COMPOSITE,
};
// A maptexturedef_t describes a rectangular texture,
// which is composed of one or more mappatch_t structures
// that arrange graphic patches.
@@ -40,6 +52,7 @@ typedef struct
{
// Keep name for switch changing, etc.
char name[8];
UINT8 type; // TEXTURETYPE_
INT16 width, height;
boolean holes;
@@ -50,6 +63,7 @@ typedef struct
// all loaded and prepared textures from the start of the game
extern texture_t **textures;
extern UINT8 **texturecache; // graphics data for each generated full-size texture
// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask
extern INT32 *texturewidthmask;
@@ -68,6 +82,8 @@ extern CV_PossibleValue_t Color_cons_t[];
void R_LoadTextures(void);
void R_FlushTextureCache(void);
UINT8 *R_GenerateTexture(size_t texnum);
INT32 R_GetTextureNum(INT32 texnum);
void R_CheckTextureCache(INT32 tex);
@@ -108,4 +124,8 @@ UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette);
extern INT32 numtextures;
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+34 -6
View File
@@ -68,6 +68,37 @@ typedef struct
#endif
} extracolormap_t;
typedef struct
{
lighttable_t* colormap;
INT32 x;
INT32 yl;
INT32 yh;
fixed_t iscale;
fixed_t texturemid;
UINT8* source; // first pixel in a column
UINT8* lightmap; // lighting only
// translucency stuff here
UINT8* transmap;
// translation stuff here
UINT8* translation;
struct r_lightlist_s* lightlist;
INT32 numlights;
INT32 maxlights;
//Fix TUTIFRUTI
INT32 texheight;
INT32 sourcelength;
} drawcolumndata_t;
extern drawcolumndata_t g_dc;
//
// INTERNAL MAP TYPES used by play and refresh
//
@@ -527,9 +558,6 @@ typedef struct seg_s
float flength; // length of the seg, used by hardware renderer
#endif
// Why slow things down by calculating lightlists for every thick side?
size_t numlights;
r_lightlist_t *rlights;
polyobj_t *polyseg;
boolean dontrenderme;
@@ -610,11 +638,11 @@ typedef struct drawseg_s
struct ffloor_s *thicksides[MAXFFLOORS];
INT16 *thicksidecol;
INT32 numthicksides;
fixed_t frontscale[MAXVIDWIDTH];
fixed_t *frontscale;
UINT8 portalpass; // if > 0 and <= portalrender, do not affect sprite clipping
fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures
fixed_t *maskedtextureheight; // For handling sloped midtextures
vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes
} drawseg_t;
@@ -668,7 +696,7 @@ typedef struct
INT16 height;
INT16 leftoffset; // pixels to the left of origin
INT16 topoffset; // pixels below the origin
INT32 columnofs[8]; // only [width] used
INT32 columnofs[]; // only [width] used
// the [0] is &columnofs[width]
} ATTRPACK softwarepatch_t;
+89 -200
View File
@@ -15,6 +15,8 @@
/// not the architecture of the frame buffer.
/// The frame buffer is a linear one, and we need only the base address.
#include <algorithm>
#include "doomdef.h"
#include "doomstat.h"
#include "r_local.h"
@@ -38,47 +40,14 @@
/** \brief view info
*/
INT32 viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy;
/** \brief pointer to the start of each line of the screen,
*/
UINT8 *ylookup[MAXVIDHEIGHT*4];
/** \brief pointer to the start of each line of the screen, for view1 (splitscreen)
*/
UINT8 *ylookup1[MAXVIDHEIGHT*4];
/** \brief pointer to the start of each line of the screen, for view2 (splitscreen)
*/
UINT8 *ylookup2[MAXVIDHEIGHT*4];
/** \brief pointer to the start of each line of the screen, for view3 (splitscreen)
*/
UINT8 *ylookup3[MAXVIDHEIGHT*4];
/** \brief pointer to the start of each line of the screen, for view4 (splitscreen)
*/
UINT8 *ylookup4[MAXVIDHEIGHT*4];
/** \brief x byte offset for columns inside the viewwindow,
so the first column starts at (SCRWIDTH - VIEWWIDTH)/2
*/
INT32 columnofs[MAXVIDWIDTH*4];
UINT8 *topleft;
INT32 linesize, viewwidth, viewheight, viewwindowx, viewwindowy;
UINT8 *renderscreen; // haleyjd
// =========================================================================
// COLUMN DRAWING CODE STUFF
// =========================================================================
lighttable_t *dc_colormap;
INT32 dc_x = 0, dc_yl = 0, dc_yh = 0;
fixed_t dc_iscale, dc_texturemid;
UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit,
// soo lets make it a byte on all system for the ASM code
UINT8 *dc_source;
INT32 dc_sourcelength;
drawcolumndata_t g_dc;
// -----------------------
// translucency stuff here
@@ -88,42 +57,34 @@ INT32 dc_sourcelength;
UINT8 *transtables; // translucency tables
UINT8 *blendtables[NUMBLENDMAPS];
/** \brief R_DrawTransColumn uses this
*/
UINT8 *dc_transmap; // one of the translucency tables
// --------------------------------------------
// c drawer routines
// --------------------------------------------
// ----------------------
// translation stuff here
// ----------------------
/** \brief R_DrawTranslatedColumn uses this
*/
UINT8 *dc_translation;
struct r_lightlist_s *dc_lightlist = NULL;
INT32 dc_numlights = 0, dc_maxlights, dc_texheight;
coldrawfunc_t *colfunc;
coldrawfunc_t *colfuncs[COLDRAWFUNC_MAX];
int colfunctype;
// =========================================================================
// SPAN DRAWING CODE STUFF
// =========================================================================
INT32 ds_y, ds_x1, ds_x2;
lighttable_t *ds_colormap;
fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
UINT8 *ds_source; // points to the start of a flat
UINT8 *ds_transmap; // one of the translucency tables
drawspandata_t g_ds;
// Vectors for Software's tilted slope drawers
floatv3_t *ds_su, *ds_sv, *ds_sz;
floatv3_t *ds_sup, *ds_svp, *ds_szp;
float focallengthf, zeroheight;
/** \brief Variable flat sizes
*/
float focallengthf;
UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
// For, uh, tilted lighting, duh.
//static INT32 *tiltlighting;
// --------------------------------------------
// c drawer routines
// --------------------------------------------
spandrawfunc_t *spanfunc;
spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX];
// ==========================================================================
// OLD DOOM FUZZY EFFECT
@@ -147,73 +108,10 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
static UINT8 **translationtablecache[TT_CACHE_SIZE] = {NULL};
static UINT8 **localtranslationtablecache[MAXLOCALSKINS] = {NULL};
// See also the enum skincolors_t
// TODO Callum: Can this be translated?
/*
const char *Color_Names[MAXSKINCOLORS] =
{
"None", // SKINCOLOR_NONE
"White", // SKINCOLOR_WHITE
"Silver", // SKINCOLOR_SILVER
"Grey", // SKINCOLOR_GREY
"Black", // SKINCOLOR_BLACK
"Cyan", // SKINCOLOR_CYAN
"Teal", // SKINCOLOR_TEAL
"Steel_Blue",// SKINCOLOR_STEEL
"Blue", // SKINCOLOR_BLUE
"Peach", // SKINCOLOR_PEACH
"Tan", // SKINCOLOR_TAN
"Pink", // SKINCOLOR_PINK
"Lavender", // SKINCOLOR_LAVENDER
"Purple", // SKINCOLOR_PURPLE
"Orange", // SKINCOLOR_ORANGE
"Rosewood", // SKINCOLOR_ROSEWOOD
"Beige", // SKINCOLOR_BEIGE
"Brown", // SKINCOLOR_BROWN
"Red", // SKINCOLOR_RED
"Dark_Red", // SKINCOLOR_DARKRED
"Neon_Green",// SKINCOLOR_NEONGREEN
"Green", // SKINCOLOR_GREEN
"Zim", // SKINCOLOR_ZIM
"Olive", // SKINCOLOR_OLIVE
"Yellow", // SKINCOLOR_YELLOW
"Gold" // SKINCOLOR_GOLD
};
const UINT8 Color_Opposite[MAXSKINCOLORS*2] =
{
SKINCOLOR_NONE,8, // SKINCOLOR_NONE
SKINCOLOR_BLACK,10, // SKINCOLOR_WHITE
SKINCOLOR_GREY,4, // SKINCOLOR_SILVER
SKINCOLOR_SILVER,12,// SKINCOLOR_GREY
SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK
SKINCOLOR_NONE,8, // SKINCOLOR_CYAN
SKINCOLOR_NONE,8, // SKINCOLOR_TEAL
SKINCOLOR_NONE,8, // SKINCOLOR_STEEL
SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE
SKINCOLOR_NONE,8, // SKINCOLOR_PEACH
SKINCOLOR_NONE,8, // SKINCOLOR_TAN
SKINCOLOR_NONE,8, // SKINCOLOR_PINK
SKINCOLOR_NONE,8, // SKINCOLOR_LAVENDER
SKINCOLOR_NONE,8, // SKINCOLOR_PURPLE
SKINCOLOR_BLUE,12, // SKINCOLOR_ORANGE
SKINCOLOR_NONE,8, // SKINCOLOR_ROSEWOOD
SKINCOLOR_NONE,8, // SKINCOLOR_BEIGE
SKINCOLOR_NONE,8, // SKINCOLOR_BROWN
SKINCOLOR_GREEN,5, // SKINCOLOR_RED
SKINCOLOR_NONE,8, // SKINCOLOR_DARKRED
SKINCOLOR_NONE,8, // SKINCOLOR_NEONGREEN
SKINCOLOR_RED,11, // SKINCOLOR_GREEN
SKINCOLOR_PURPLE,3, // SKINCOLOR_ZIM
SKINCOLOR_NONE,8, // SKINCOLOR_OLIVE
SKINCOLOR_NONE,8, // SKINCOLOR_YELLOW
SKINCOLOR_NONE,8 // SKINCOLOR_GOLD
};
*/
CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
static void R_GenerateBlendTables(void);
/** \brief Initializes the translucency tables used by the Software renderer.
*/
void R_InitTranslucencyTables(void)
@@ -221,8 +119,7 @@ void R_InitTranslucencyTables(void)
// Load here the transparency lookup tables 'TRANSx0'
// NOTE: the TRANSx0 resources MUST BE aligned on 64k for the asm
// optimised code (in other words, transtables pointer low word is 0)
transtables = Z_MallocAlign(NUMTRANSTABLES*0x10000, PU_STATIC,
NULL, 16);
transtables = static_cast<UINT8*>(Z_MallocAlign(NUMTRANSTABLES*0x10000, PU_STATIC, NULL, 16));
W_ReadLump(W_GetNumForName("TRANS10"), transtables);
W_ReadLump(W_GetNumForName("TRANS20"), transtables+0x10000);
@@ -283,10 +180,10 @@ static void BlendTab_Subtractive(UINT8 *table, int style, UINT8 blendamt)
RGBA_t frontrgba = V_GetColor(fg);
RGBA_t result;
result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF);
result.s.red = max(0, result.s.red - blendamt);
result.s.green = max(0, result.s.green - blendamt);
result.s.blue = max(0, result.s.blue - blendamt);
result.rgba = ASTBlendPixel(backrgba, frontrgba, style, 0xFF);
result.s.red = std::max(0, result.s.red - blendamt);
result.s.green = std::max(0, result.s.green - blendamt);
result.s.blue = std::max(0, result.s.blue - blendamt);
table[((bg * 0x100) + fg)] = GetColorLUT(&transtab_lut, result.s.red, result.s.green, result.s.blue);
}
@@ -339,17 +236,17 @@ static void BlendTab_GenerateMaps(INT32 tab, INT32 style, void (*genfunc)(UINT8
for (; i < num; i++)
{
const size_t offs = (0x10000 * i);
const UINT16 alpha = min(amtmul * i, 0xFF);
const UINT16 alpha = std::fmin(amtmul * i, 0xFF);
genfunc(blendtables[tab] + offs, style, alpha);
}
}
void R_GenerateBlendTables(void)
static void R_GenerateBlendTables(void)
{
INT32 i;
for (i = 0; i < NUMBLENDMAPS; i++)
blendtables[i] = Z_MallocAlign(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL, 16);
blendtables[i] = static_cast<UINT8*>(Z_MallocAlign(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL, 16));
InitColorLUT(&transtab_lut, pLocalPalette, false);
@@ -370,8 +267,8 @@ void R_GenerateBlendTables(void)
BlendTab_Modulative(blendtables[blendtab_modulate]);
}
#define ClipBlendLevel(style, trans) max(min((trans), BlendTab_Count[BlendTab_FromStyle[style]]-1), 0)
#define ClipTransLevel(trans) max(min((trans), NUMTRANSMAPS-2), 0)
#define ClipBlendLevel(style, trans) std::max(std::min((trans), BlendTab_Count[BlendTab_FromStyle[style]]-1), 0)
#define ClipTransLevel(trans) std::max(std::min((trans), NUMTRANSMAPS-2), 0)
UINT8 *R_GetTranslucencyTable(INT32 alphalevel)
{
@@ -458,7 +355,7 @@ static UINT8* RGetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 f
{
// Allocate table for skin if necessary
if (!tt[skintableindex])
tt[skintableindex] = Z_Calloc(MAXTRANSLATIONS * sizeof(UINT8**), PU_STATIC, NULL);
tt[skintableindex] = static_cast<UINT8**>(Z_Calloc(MAXTRANSLATIONS * sizeof(UINT8**), PU_STATIC, NULL));
// Get colormap
ret = tt[skintableindex][color];
@@ -468,7 +365,7 @@ static UINT8* RGetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 f
// Generate the colormap if necessary
if (!ret)
{
ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8);
ret = static_cast<UINT8*>(Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8));
K_GenerateKartColormap(ret, skinnum, color, local); //R_GenerateTranslationColormap(ret, skinnum, color); // SRB2kart
// Cache the colormap if desired
@@ -540,19 +437,6 @@ void R_FlushTranslationColormapCache(void)
memset(localtranslationtablecache[i], 0, MAXTRANSLATIONS * sizeof(UINT8**));
}
/*
UINT8 R_GetColorByName(const char *name)
{
UINT8 color = (UINT8)atoi(name);
if (color > 0 && color < MAXSKINCOLORS)
return color;
for (color = 1; color < MAXSKINCOLORS; color++)
if (!stricmp(Color_Names[color], name))
return color;
return 0;
}
*/
// ==========================================================================
// COMMON DRAWER FOR 8 AND 16 BIT COLOR MODES
// ==========================================================================
@@ -572,39 +456,44 @@ UINT8 R_GetColorByName(const char *name)
\param height hieght of buffer
\return void
*/
static void R_AllocViewMemory(void)
{
negonearray = static_cast<INT16*>(Z_Realloc(negonearray, sizeof(*negonearray) * viewwidth, PU_STATIC, NULL));
screenheightarray = static_cast<INT16*>(Z_Realloc(screenheightarray, sizeof(*screenheightarray) * viewwidth, PU_STATIC, NULL));
floorclip = static_cast<INT16*>(Z_Realloc(floorclip, sizeof(*floorclip) * viewwidth, PU_STATIC, NULL));
ceilingclip = static_cast<INT16*>(Z_Realloc(ceilingclip, sizeof(*ceilingclip) * viewwidth, PU_STATIC, NULL));
frontscale = static_cast<fixed_t*>(Z_Realloc(frontscale, sizeof(*frontscale) * viewwidth, PU_STATIC, NULL));
xtoviewangle = static_cast<angle_t*>(Z_Realloc(xtoviewangle, sizeof(*xtoviewangle) * (viewwidth + 1), PU_STATIC, NULL));
R_AllocSegMemory();
R_AllocClipSegMemory();
R_AllocPlaneMemory();
#ifdef FLOORSPLATS
R_AllocFloorSpriteTables();
#endif
R_AllocVisSpriteMemory();
}
void R_InitViewBuffer(INT32 width, INT32 height)
{
INT32 i, bytesperpixel = vid.bpp;
if (width > MAXVIDWIDTH)
width = MAXVIDWIDTH;
if (height > MAXVIDHEIGHT)
height = MAXVIDHEIGHT;
if (bytesperpixel < 1 || bytesperpixel > 4)
I_Error("R_InitViewBuffer: wrong bytesperpixel value %d\n", bytesperpixel);
R_AllocViewMemory();
viewwindowx = 0;
viewwindowy = 0;
// Column offset for those columns of the view window, but relative to the entire screen
for (i = 0; i < width; i++)
columnofs[i] = (viewwindowx + i) * bytesperpixel;
// Precalculate all row offsets.
for (i = 0; i < height; i++)
{
ylookup[i] = ylookup1[i] = screens[0] + i*vid.width*bytesperpixel;
if (splitscreen == 1)
ylookup2[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel;
else
ylookup2[i] = screens[0] + i*vid.width*bytesperpixel + (viewwidth*bytesperpixel);
ylookup3[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel;
ylookup4[i] = screens[0] + (i+viewheight)*vid.width*bytesperpixel + (viewwidth*bytesperpixel);
}
linesize = vid.width; // killough 11/98
renderscreen = vid.screens[0]; // haleyjd 07/02/14
}
/** \brief viewborder patches lump numbers
@@ -626,6 +515,28 @@ void R_InitViewBorder(void)
viewborderlump[BRDR_BR] = W_GetNumForName("brdr_br");
}
/** \brief The R_VideoErase function
Copy a screen buffer.
\param ofs offest from buffer
\param count bytes to erase
\return void
*/
void R_VideoErase(size_t ofs, INT32 count)
{
// LFB copy.
// This might not be a good idea if memcpy
// is not optimal, e.g. byte by byte on
// a 32bit CPU, as GNU GCC/Linux libc did
// at one point.
M_Memcpy(vid.screens[0] + ofs, vid.screens[1] + ofs, count);
}
#if 0
/** \brief R_FillBackScreen
@@ -648,7 +559,7 @@ void R_FillBackScreen(void)
return;
src = scr_borderpatch;
dest = screens[1];
dest = vid.screens[1];
for (y = 0; y < vid.height; y++)
{
@@ -699,30 +610,7 @@ void R_FillBackScreen(void)
V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + viewheight, 1,
W_CacheLumpNum(viewborderlump[BRDR_BR], PU_CACHE));
}
#endif
/** \brief The R_VideoErase function
Copy a screen buffer.
\param ofs offest from buffer
\param count bytes to erase
\return void
*/
void R_VideoErase(size_t ofs, INT32 count)
{
// LFB copy.
// This might not be a good idea if memcpy
// is not optimal, e.g. byte by byte on
// a 32bit CPU, as GNU GCC/Linux libc did
// at one point.
M_Memcpy(screens[0] + ofs, screens[1] + ofs, count);
}
#if 0
/** \brief The R_DrawViewBorder
Draws the border around the view
@@ -766,13 +654,14 @@ void R_DrawViewBorder(void)
side <<= 1;
// simpler using our VID_Blit routine
VID_BlitLinearScreen(screens[1] + ofs, screens[0] + ofs, side, viewheight - 1,
VID_BlitLinearScreen(vid.screens[1] + ofs, vid.screens[0] + ofs, side, viewheight - 1,
vid.width, vid.width);
}
#endif
// ==========================================================================
// INCLUDE 8bpp DRAWING CODE HERE
// INCLUDE DRAWING CODE HERE
// ==========================================================================
#include "r_draw8.c"
#include "r_draw_column.cpp"
#include "r_draw_span.cpp"
+155 -74
View File
@@ -14,72 +14,143 @@
#ifndef __R_DRAW__
#define __R_DRAW__
#ifdef __cplusplus
extern "C" {
#endif
#include "r_defs.h"
#include "r_things.h"
#include "r_skins.h"
// -------------------------------
// COMMON STUFF FOR 8bpp AND 16bpp
// -------------------------------
extern UINT8 *ylookup[MAXVIDHEIGHT*4];
extern UINT8 *ylookup1[MAXVIDHEIGHT*4];
extern UINT8 *ylookup2[MAXVIDHEIGHT*4];
extern UINT8 *ylookup3[MAXVIDHEIGHT*4];
extern UINT8 *ylookup4[MAXVIDHEIGHT*4];
extern INT32 columnofs[MAXVIDWIDTH*4];
extern UINT8 *topleft;
extern UINT8 *renderscreen;
extern INT32 linesize;
// -------------------------
// COLUMN DRAWING CODE STUFF
// -------------------------
FUNCINLINE static ATTRINLINE UINT8 *R_Address(INT32 px, INT32 py)
{
return renderscreen + (py + viewwindowy) * linesize + (viewwindowx + px);
}
extern lighttable_t *dc_colormap;
extern INT32 dc_x, dc_yl, dc_yh;
extern fixed_t dc_iscale, dc_texturemid;
extern UINT8 dc_hires;
extern UINT8 *dc_source; // first pixel in a column
// translucency stuff here
extern UINT8 *dc_transmap;
// translation stuff here
extern UINT8 *dc_translation;
extern struct r_lightlist_s *dc_lightlist;
extern INT32 dc_numlights, dc_maxlights;
//Fix TUTIFRUTI
extern INT32 dc_texheight;
// -----------------------
// SPAN DRAWING CODE STUFF
// -----------------------
extern INT32 ds_y, ds_x1, ds_x2;
extern lighttable_t *ds_colormap;
extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
extern INT32 ds_waterofs, ds_bgofs;
extern UINT8 *ds_source; // start of a 64*64 tile image
extern INT32 dc_sourcelength;
extern UINT8 *ds_transmap;
extern INT32 ds_bgofs;
typedef struct {
float x, y, z;
} floatv3_t;
typedef struct
{
INT32 y;
INT32 x1;
INT32 x2;
lighttable_t* colormap;
lighttable_t* translation;
fixed_t xfrac;
fixed_t yfrac;
fixed_t xstep;
fixed_t ystep;
INT32 waterofs;
INT32 bgofs;
fixed_t xoffs;
fixed_t yoffs;
visplane_t *currentplane;
UINT8 *source;
UINT8 *transmap;
float zeroheight;
// Vectors for Software's tilted slope drawers
floatv3_t sup;
floatv3_t svp;
floatv3_t szp;
floatv3_t slope_origin;
floatv3_t slope_u;
floatv3_t slope_v;
// Variable flat sizes
UINT32 nflatxshift;
UINT32 nflatyshift;
UINT32 nflatshiftup;
UINT32 nflatmask;
fixed_t planeheight;
lighttable_t **planezlight;
//
// Water ripple effect
// Needs the height of the plane, and the vertical position of the span.
// Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted.
//
struct
{
INT32 offset;
fixed_t xfrac, yfrac;
boolean active;
} planeripple;
} drawspandata_t;
extern drawspandata_t g_ds;
// Draws a single visplane.
void R_DrawSinglePlane(drawspandata_t* ds, visplane_t *pl, boolean allow_parallel);
// Vectors for Software's tilted slope drawers
extern floatv3_t *ds_su, *ds_sv, *ds_sz;
extern floatv3_t *ds_sup, *ds_svp, *ds_szp;
extern float focallengthf, zeroheight;
// Variable flat sizes
extern UINT32 nflatxshift;
extern UINT32 nflatyshift;
extern UINT32 nflatshiftup;
extern UINT32 nflatmask;
extern float focallengthf;
typedef void (coldrawfunc_t)(drawcolumndata_t*);
typedef void (spandrawfunc_t)(drawspandata_t*);
#define BASEDRAWFUNC 0
enum
{
COLDRAWFUNC_BASE = BASEDRAWFUNC,
COLDRAWFUNC_FUZZY,
COLDRAWFUNC_TRANS,
COLDRAWFUNC_SHADOWED,
COLDRAWFUNC_TRANSTRANS,
COLDRAWFUNC_TWOSMULTIPATCH,
COLDRAWFUNC_TWOSMULTIPATCHTRANS,
COLDRAWFUNC_FOG,
COLDRAWFUNC_MAX
};
extern int colfunctype;
extern coldrawfunc_t *colfunc;
extern coldrawfunc_t *colfuncs[COLDRAWFUNC_MAX];
enum
{
SPANDRAWFUNC_BASE = BASEDRAWFUNC,
SPANDRAWFUNC_TRANS,
SPANDRAWFUNC_TILTED,
SPANDRAWFUNC_TILTEDTRANS,
SPANDRAWFUNC_SPLAT,
SPANDRAWFUNC_TRANSSPLAT,
SPANDRAWFUNC_TILTEDSPLAT,
SPANDRAWFUNC_TILTEDTRANSSPLAT,
SPANDRAWFUNC_WATER,
SPANDRAWFUNC_TILTEDWATER,
SPANDRAWFUNC_FOG,
SPANDRAWFUNC_TILTEDFOG,
SPANDRAWFUNC_MAX
};
extern spandrawfunc_t *spanfunc;
extern spandrawfunc_t *spanfuncs[SPANDRAWFUNC_MAX];
void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column);
/// \brief Top border
#define BRDR_T 0
@@ -138,7 +209,6 @@ enum
extern UINT8 *blendtables[NUMBLENDMAPS];
void R_InitTranslucencyTables(void);
void R_GenerateBlendTables(void);
UINT8 *R_GetTranslucencyTable(INT32 alphalevel);
UINT8 *R_GetBlendTable(int style, INT32 alphalevel);
@@ -161,33 +231,44 @@ void R_DrawViewBorder(void);
#define TRANSPARENTPIXEL 247
// -----------------
// 8bpp DRAWING CODE
// DRAWING CODE
// -----------------
void R_DrawColumn_8(void);
#define R_DrawWallColumn_8 R_DrawColumn_8
void R_DrawShadeColumn_8(void);
void R_DrawTranslucentColumn_8(void);
// column drawers
void R_DrawColumn(drawcolumndata_t* dc);
void R_DrawColumnShadowed(drawcolumndata_t* dc);
void R_DrawTranslatedColumn_8(void);
void R_DrawTranslatedTranslucentColumn_8(void);
void R_DrawSpan_8(void);
void R_CalcTiltedLighting(fixed_t start, fixed_t end);
void R_DrawTiltedSpan_8(void);
void R_DrawTiltedTranslucentSpan_8(void);
#ifndef NOWATER
void R_DrawTiltedTranslucentWaterSpan_8(void);
void R_DrawTranslucentColumn(drawcolumndata_t* dc);
void R_DrawTranslatedColumn(drawcolumndata_t* dc);
void R_DrawTranslatedTranslucentColumn(drawcolumndata_t* dc);
void R_Draw2sMultiPatchColumn(drawcolumndata_t* dc);
void R_Draw2sMultiPatchTranslucentColumn(drawcolumndata_t* dc);
void R_DrawFogColumn(drawcolumndata_t* dc);
// span drawers
void R_DrawSpan(drawspandata_t* ds);
void R_DrawSpan_Tilted(drawspandata_t* ds);
void R_DrawTranslucentSpan_Tilted(drawspandata_t* ds);
void R_DrawTranslucentWaterSpan_Tilted(drawspandata_t* ds);
void R_DrawTranslucentSpan(drawspandata_t* ds);
void R_DrawTranslucentWaterSpan(drawspandata_t* ds);
void R_DrawFogSpan(drawspandata_t* ds);
void R_DrawFogSpan_Tilted(drawspandata_t* ds);
void R_DrawSplat_Tilted(drawspandata_t* ds);
void R_DrawSplat(drawspandata_t* ds);
void R_DrawTranslucentSplat(drawspandata_t* ds);
void R_DrawTranslucentSplat_Tilted(drawspandata_t* ds);
#ifdef __cplusplus
} // extern "C"
#endif
void R_DrawTiltedSplat_8(void);
void R_DrawSplat_8(void);
void R_DrawTranslucentSplat_8(void);
void R_DrawTranslucentSpan_8(void);
void R_DrawTranslucentWaterSpan_8(void);
void R_Draw2sMultiPatchColumn_8(void);
void R_Draw2sMultiPatchTranslucentColumn_8(void);
void R_DrawFogSpan_8(void);
void R_DrawFogColumn_8(void);
void R_DrawColumnShadowed_8(void);
// =========================================================================
#endif // __R_DRAW__
-1818
View File
File diff suppressed because it is too large. Load diff
+356
View File
@@ -0,0 +1,356 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2000 by DooM Legacy Team.
// Copyright (C) 1996 by id Software, Inc.
//
// 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 r_draw_column.cpp
/// \brief column drawer functions
/// \note no includes because this is included as part of r_draw.cpp
// ==========================================================================
// COLUMNS
// ==========================================================================
// A column is a vertical slice/span of a wall texture that uses
// a has a constant z depth from top to bottom.
//
enum DrawColumnType
{
DC_BASIC = 0x0000,
DC_COLORMAP = 0x0001,
DC_TRANSMAP = 0x0002,
DC_HOLES = 0x0004,
DC_LIGHTLIST = 0x0008,
};
template<DrawColumnType Type>
static constexpr UINT8 R_GetColumnTranslated(drawcolumndata_t* dc, UINT8 col, const UINT8 * restrict colormap)
{
if constexpr (Type & DrawColumnType::DC_COLORMAP)
{
col = dc->translation[col];
}
return colormap[col];
}
template<DrawColumnType Type>
static constexpr UINT8 R_GetColumnTranslucent(drawcolumndata_t* dc, UINT8 * restrict dest, UINT8 col, const UINT8 * restrict colormap)
{
col = R_GetColumnTranslated<Type>(dc, col, colormap);
if constexpr (Type & DrawColumnType::DC_TRANSMAP)
{
return *(dc->transmap + (col << 8) + (*dest));
}
else
{
return col;
}
}
template<DrawColumnType Type>
static constexpr UINT8 R_DrawColumnPixel(drawcolumndata_t* dc, UINT8 * restrict dest, UINT32 bit, const restrict UINT8 *source, const restrict UINT8 *colormap)
{
UINT8 col = source[bit];
if constexpr (Type & DrawColumnType::DC_HOLES)
{
if (col == TRANSPARENTPIXEL)
{
return *dest;
}
}
return R_GetColumnTranslucent<Type>(dc, dest, col, colormap);
}
/** \brief The R_DrawColumn function
Experiment to make software go faster. Taken from the Boom source
*/
template<DrawColumnType Type>
static void R_DrawColumnTemplate(drawcolumndata_t *dc)
{
INT32 count;
count = dc->yh - dc->yl;
if (count < 0) // Zero length, column does not exceed a pixel.
{
return;
}
if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height)
{
return;
}
if constexpr (Type & DrawColumnType::DC_LIGHTLIST)
{
constexpr DrawColumnType NewType = static_cast<DrawColumnType>(Type & ~DC_LIGHTLIST);
INT32 i, height, bheight = 0, solid = 0;
drawcolumndata_t dc_copy = *dc;
const INT32 realyh = dc_copy.yh;
// This runs through the lightlist from top to bottom and cuts up the column accordingly.
for (i = 0; i < dc_copy.numlights; i++)
{
// If the height of the light is above the column, get the colormap
// anyway because the lighting of the top should be affected.
solid = dc_copy.lightlist[i].flags & FF_CUTSOLIDS;
height = dc_copy.lightlist[i].height >> LIGHTSCALESHIFT;
if (solid)
{
bheight = dc_copy.lightlist[i].botheight >> LIGHTSCALESHIFT;
if (bheight < height)
{
// confounded slopes sometimes allow partial invertedness,
// even including cases where the top and bottom heights
// should actually be the same!
// swap the height values as a workaround for this quirk
INT32 temp = height;
height = bheight;
bheight = temp;
}
}
if (height <= dc_copy.yl)
{
dc_copy.colormap = dc_copy.lightlist[i].rcolormap;
if (encoremap)
{
dc_copy.colormap += COLORMAP_REMAPOFFSET;
}
if (solid && dc_copy.yl < bheight)
{
dc_copy.yl = bheight;
}
continue;
}
// Found a break in the column!
dc_copy.yh = height;
if (dc_copy.yh > realyh)
{
dc_copy.yh = realyh;
}
R_DrawColumnTemplate<NewType>(&dc_copy);
if (solid)
{
dc_copy.yl = bheight;
}
else
{
dc_copy.yl = dc_copy.yh + 1;
}
dc_copy.colormap = dc_copy.lightlist[i].rcolormap;
if (encoremap)
{
dc_copy.colormap += COLORMAP_REMAPOFFSET;
}
}
dc_copy.yh = realyh;
if (dc_copy.yl <= realyh)
{
R_DrawColumnTemplate<NewType>(&dc_copy);
}
}
else
{
// Inner loop that does the actual texture mapping,
// e.g. a DDA-lile scaling.
// This is as fast as it gets. (Yeah, right!!! -- killough)
//
// killough 2/1/98: more performance tuning
intptr_t frac;
const intptr_t fracstep = dc->iscale;
const intptr_t heightmask = dc->sourcelength-1;
constexpr INT32 npow2min = -1;
const INT32 npow2max = dc->sourcelength;
const INT32 stride = vid.width;
const UINT8 * restrict source = dc->source;
const lighttable_t * restrict colormap = dc->colormap;
// Framebuffer destination address.
UINT8 * restrict dest = R_Address(dc->x, dc->yl);
count++;
// Determine scaling, which is the only mapping to be done.
frac = (dc->texturemid + FixedMul((dc->yl << FRACBITS) - centeryfrac, fracstep));
switch (heightmask)
{
case 255:
case 127:
{
while(count--)
{
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
dest += stride;
frac += fracstep;
}
}
break;
case -1:
{
if (frac < 0)
// adjust in case we underread
frac += FRACUNIT;
// texture has no height, so just go
while (--count >= 0)
{
*dest = R_DrawColumnPixel<Type>(dc, dest, frac>>FRACBITS, source, colormap);
dest += stride;
frac += fracstep;
}
}
break;
default:
{
if (!(dc->sourcelength & heightmask)) // power of 2 -- killough
{
while ((count -= 2) >= 0) // texture height is a power of 2 -- killough
{
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
dest += stride;
frac += fracstep;
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
dest += stride;
frac += fracstep;
}
if (count & 1)
{
*dest = R_DrawColumnPixel<Type>(dc, dest, (frac>>FRACBITS) & heightmask, source, colormap);
}
}
else
{
const intptr_t fixed_heightmask = dc->texheight << FRACBITS;
if (frac < 0)
{
while ((frac += fixed_heightmask) < 0)
{
;
}
}
else
{
while (frac >= fixed_heightmask)
{
frac -= fixed_heightmask;
}
}
do
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix
// -1 is the lower clamp bound because column posts have a "safe" byte before the real data
// and a few bytes after as well
*dest = R_DrawColumnPixel<Type>(dc, dest, CLAMP((frac >> FRACBITS), npow2min, npow2max), source, colormap);
dest += stride;
#if __SIZEOF_POINTER__ < 8 // 64-bit systems have large enough numbers for this to be a non-issue
// Avoid overflow.
if (fracstep > 0x7FFFFFFF - frac)
{
frac += fracstep - fixed_heightmask;
}
else
#endif
{
frac += fracstep;
}
while (frac >= fixed_heightmask)
{
frac -= fixed_heightmask;
}
}
while (--count);
}
}
break;
}
}
}
#define DEFINE_COLUMN_FUNC(name, flags) \
void name(drawcolumndata_t *dc) \
{ \
constexpr DrawColumnType opt = static_cast<DrawColumnType>(flags); \
R_DrawColumnTemplate<opt>(dc); \
}
DEFINE_COLUMN_FUNC(R_DrawColumn, DC_BASIC)
DEFINE_COLUMN_FUNC(R_DrawTranslucentColumn, DC_TRANSMAP)
DEFINE_COLUMN_FUNC(R_DrawTranslatedColumn, DC_COLORMAP)
DEFINE_COLUMN_FUNC(R_DrawColumnShadowed, DC_LIGHTLIST)
DEFINE_COLUMN_FUNC(R_DrawTranslatedTranslucentColumn, DC_COLORMAP|DC_TRANSMAP)
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchColumn, DC_HOLES)
DEFINE_COLUMN_FUNC(R_Draw2sMultiPatchTranslucentColumn, DC_HOLES|DC_TRANSMAP)
/** \brief The R_DrawFogColumn function
Fog wall.
*/
void R_DrawFogColumn(drawcolumndata_t* dc)
{
INT32 count;
UINT8 * restrict dest;
count = dc->yh - dc->yl;
// Zero length, column does not exceed a pixel.
if (count < 0)
{
return;
}
if ((unsigned)dc->x >= (unsigned)vid.width || dc->yl < 0 || dc->yh >= vid.height)
{
return;
}
// Framebuffer destination address.
dest = R_Address(dc->x, dc->yl);
const INT32 stride = vid.width;
const lighttable_t * restrict colormap = dc->colormap;
// Determine scaling, which is the only mapping to be done.
do
{
// Simple. Apply the colormap to what's already on the screen.
*dest = colormap[*dest];
dest += stride;
} while (count--);
}
+446
View File
@@ -0,0 +1,446 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2000 by DooM Legacy Team.
// Copyright (C) 1996 by id Software, Inc.
//
// 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 r_draw_span.cpp
/// \brief span drawer functions
/// \note no includes because this is included as part of r_draw.cpp
#ifdef HAVE_THREADS
#ifdef _WIN32
#include <windows.h>
#define local_for_thread static __thread
#else
#include <threads.h>
#define local_for_thread thread_local static
#endif
#else
#define local_for_thread static
#endif
// ==========================================================================
// SPANS
// ==========================================================================
#define SPANSIZE 16
#define INVSPAN 0.0625f
// <Callum> 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size)
#define MAXFLATBYTES 4194303
#define PLANELIGHTFLOAT ((float)BASEVIDWIDTH * BASEVIDWIDTH / stride / ds->zeroheight / 21.0f * FIXED_TO_FLOAT(fovtan))
enum DrawSpanType
{
DS_BASIC = 0x0000,
DS_COLORMAP = 0x0001,
DS_TRANSMAP = 0x0002,
DS_HOLES = 0x0004,
DS_RIPPLE = 0x0008,
};
template<DrawSpanType Type>
static constexpr UINT8 R_GetSpanTranslucent(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT8 col)
{
col = colormap[col];
if constexpr (Type & DrawSpanType::DS_TRANSMAP)
{
return *(ds->transmap + (col << 8) + (*dsrc));
}
else
{
return col;
}
}
template<DrawSpanType Type>
static constexpr UINT8 R_DrawSpanPixel(drawspandata_t* ds, UINT8 *dsrc, const UINT8 *colormap, UINT32 bit, const UINT8 *source)
{
UINT8 col = source[bit];
if constexpr (Type & DrawSpanType::DS_HOLES)
{
if (col == TRANSPARENTPIXEL)
{
return *dsrc;
}
}
return R_GetSpanTranslucent<Type>(ds, dsrc, colormap, col);
}
/** \brief The R_DrawSpan_8 function
Draws the actual span.
*/
template<DrawSpanType Type>
static void R_DrawSpanTemplate(drawspandata_t* ds)
{
UINT32 xposition;
UINT32 yposition;
UINT32 xstep, ystep;
UINT32 bit;
UINT8 * restrict dest = R_Address(ds->x1, ds->y);
UINT8 * restrict dsrc;
const UINT8 * restrict deststop = vid.screens[0] + vid.rowbytes * vid.height;
if (dest+8 > deststop)
{
return;
}
intptr_t count = (ds->x2 - ds->x1 + 1);
size_t i;
xposition = ds->xfrac; yposition = ds->yfrac;
xstep = ds->xstep; ystep = ds->ystep;
const UINT8 * restrict source = ds->source;
const UINT8 * restrict colormap = ds->colormap;
if constexpr (Type & DS_RIPPLE)
{
yposition += ds->waterofs;
}
// SoM: we only need 6 bits for the integer part (0 thru 63) so the rest
// can be used for the fraction part. This allows calculation of the memory address in the
// texture with two shifts, an OR and one AND. (see below)
// for texture sizes > 64 the amount of precision we can allow will decrease, but only by one
// bit per power of two (obviously)
// Ok, because I was able to eliminate the variable spot below, this function is now FASTER
// than the original span renderer. Whodathunkit?
xposition <<= ds->nflatshiftup; yposition <<= ds->nflatshiftup;
xstep <<= ds->nflatshiftup; ystep <<= ds->nflatshiftup;
if constexpr (Type & DS_RIPPLE)
{
dsrc = vid.screens[1] + (ds->y + ds->bgofs) * vid.width + ds->x1;
}
else
{
dsrc = dest;
}
while (count >= 8)
{
// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
// have the uber complicated math to calculate it now, so that was a memory write we didn't
// need!
for (i = 0; i < 8; i++)
{
bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift);
dest[i] = R_DrawSpanPixel<Type>(ds, &dsrc[i], colormap, bit, source);
xposition += xstep;
yposition += ystep;
}
dest += 8;
dsrc += 8;
count -= 8;
}
while (count-- && dest <= deststop)
{
bit = ((yposition >> ds->nflatyshift) & ds->nflatmask) | (xposition >> ds->nflatxshift);
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
dest++;
dsrc++;
xposition += xstep;
yposition += ystep;
}
}
// R_CalcTiltedLighting
// Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly.
static void R_CalcTiltedLighting(INT32 *lightbuffer, INT32 x1, INT32 x2, fixed_t start, fixed_t end)
{
// ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version
// of this function. Here's my own.
INT32 i, left = x1, right = x2;
const fixed_t step = (end-start)/(x2 - x1 + 1);
// I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once,
// but I'm too bad at coding to not crash the game trying to do that. I guess this is fast enough for now...
for (i = left; i <= right; i++)
{
lightbuffer[i] = (start += step) >> FRACBITS;
if (lightbuffer[i] < 0)
{
lightbuffer[i] = 0;
}
else if (lightbuffer[i] >= MAXLIGHTSCALE)
{
lightbuffer[i] = MAXLIGHTSCALE-1;
}
}
}
template<DrawSpanType Type>
static void R_DrawTiltedSpanTemplate(drawspandata_t* ds)
{
int width = ds->x2 - ds->x1;
float iz, uz, vz;
UINT32 u, v;
int i;
UINT8 * restrict dest = R_Address(ds->x1, ds->y);
UINT8 * restrict dsrc;
float startz, startu, startv;
float izstep, uzstep, vzstep;
float endz, endu, endv;
UINT32 stepu, stepv;
UINT32 bit;
local_for_thread INT32 *tiltlighting = NULL;
local_for_thread INT32 oldviewwidth = 0;
// dont realloc every frame pls thx
if (tiltlighting == NULL || oldviewwidth != viewwidth)
{
tiltlighting = static_cast<INT32*>(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth));
oldviewwidth = viewwidth;
}
INT32 x1 = ds->x1;
const INT32 nflatxshift = ds->nflatxshift;
const INT32 nflatyshift = ds->nflatyshift;
const INT32 nflatmask = ds->nflatmask;
const INT32 stride = vid.width;
iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx);
// Lighting is simple. It's just linear interpolation from start to end
{
float planelightfloat = PLANELIGHTFLOAT;
float lightstart, lightend;
lightend = (iz + ds->szp.x*width) * planelightfloat;
lightstart = iz * planelightfloat;
R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend));
//CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf);
}
uz = ds->sup.z + ds->sup.y*(centery-ds->y) + ds->sup.x*(ds->x1-centerx);
vz = ds->svp.z + ds->svp.y*(centery-ds->y) + ds->svp.x*(ds->x1-centerx);
const UINT8 *source = ds->source;
const UINT8 *colormap = ds->colormap;
if constexpr (Type & DS_RIPPLE)
{
dsrc = vid.screens[1] + (ds->y + ds->bgofs) * stride + ds->x1;
}
else
{
dsrc = dest;
}
#if 0 // The "perfect" reference version of this routine. Pretty slow.
// Use it only to see how things are supposed to look.
i = 0;
do
{
double z = 1.f/iz;
u = (INT64)(uz*z);
v = (INT64)(vz*z);
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
colormap = planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit);
dest++;
ds->x1++;
dsrc++;
iz += ds_szp->x;
uz += ds_sup->x;
vz += ds_svp->x;
} while (--width >= 0);
#else
startz = 1.f/iz;
startu = uz*startz;
startv = vz*startz;
izstep = ds->szp.x * SPANSIZE;
uzstep = ds->sup.x * SPANSIZE;
vzstep = ds->svp.x * SPANSIZE;
//x1 = 0;
width++;
while (width >= SPANSIZE)
{
iz += izstep;
uz += uzstep;
vz += vzstep;
endz = 1.f/iz;
endu = uz*endz;
endv = vz*endz;
stepu = (INT64)((endu - startu) * INVSPAN);
stepv = (INT64)((endv - startv) * INVSPAN);
u = (INT64)(startu);
v = (INT64)(startv);
x1 = ds->x1;
for (i = 0; i < SPANSIZE; i++)
{
bit = (((v + stepv * i) >> nflatyshift) & nflatmask) | ((u + stepu * i) >> nflatxshift);
colormap = ds->planezlight[tiltlighting[x1 + i]] + (ds->colormap - colormaps);
dest[i] = R_DrawSpanPixel<Type>(ds, &dsrc[i], colormap, bit, source);
}
ds->x1 += SPANSIZE;
dest += SPANSIZE;
dsrc += SPANSIZE;
startu = endu;
startv = endv;
width -= SPANSIZE;
}
if (width > 0)
{
if (width == 1)
{
u = (INT64)(startu);
v = (INT64)(startv);
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
ds->x1++;
}
else
{
double left = width;
iz += ds->szp.x * left;
uz += ds->sup.x * left;
vz += ds->svp.x * left;
endz = 1.f/iz;
endu = uz*endz;
endv = vz*endz;
left = 1.f/left;
stepu = (INT64)((endu - startu) * left);
stepv = (INT64)((endv - startv) * left);
u = (INT64)(startu);
v = (INT64)(startv);
for (; width != 0; width--)
{
bit = ((v >> ds->nflatyshift) & ds->nflatmask) | (u >> ds->nflatxshift);
colormap = ds->planezlight[tiltlighting[ds->x1]] + (ds->colormap - colormaps);
*dest = R_DrawSpanPixel<Type>(ds, dsrc, colormap, bit, source);
dest++;
ds->x1++;
dsrc++;
u += stepu;
v += stepv;
}
}
}
#endif
}
#define DEFINE_SPAN_FUNC(name, flags, template) \
void name(drawspandata_t* ds) \
{ \
constexpr DrawSpanType opt = static_cast<DrawSpanType>(flags); \
template<opt>(ds); \
}
#define DEFINE_SPAN_COMBO(name, flags) \
DEFINE_SPAN_FUNC(name, flags, R_DrawSpanTemplate) \
DEFINE_SPAN_FUNC(name ## _Tilted, flags, R_DrawTiltedSpanTemplate) \
DEFINE_SPAN_COMBO(R_DrawSpan, DS_BASIC)
DEFINE_SPAN_COMBO(R_DrawTranslucentSpan, DS_TRANSMAP)
DEFINE_SPAN_COMBO(R_DrawSplat, DS_HOLES)
DEFINE_SPAN_COMBO(R_DrawTranslucentSplat, DS_TRANSMAP|DS_HOLES)
DEFINE_SPAN_COMBO(R_DrawTranslucentWaterSpan, DS_TRANSMAP|DS_RIPPLE)
/** \brief The R_DrawFogSpan function
Draws the actual span with fogging.
*/
void R_DrawFogSpan(drawspandata_t* ds)
{
const UINT8 * restrict colormap = ds->colormap;
UINT8 * restrict dest = R_Address(ds->x1, ds->y);
intptr_t count = ds->x2 - ds->x1 + 1;
while (count >= 4)
{
dest[0] = colormap[dest[0]];
dest[1] = colormap[dest[1]];
dest[2] = colormap[dest[2]];
dest[3] = colormap[dest[3]];
dest += 4;
count -= 4;
}
while (count--)
{
*dest = colormap[*dest];
dest++;
}
}
void R_DrawFogSpan_Tilted(drawspandata_t* ds)
{
int width = ds->x2 - ds->x1;
float iz = ds->szp.z + ds->szp.y*(centery-ds->y) + ds->szp.x*(ds->x1-centerx);
UINT8 * restrict dest;
local_for_thread INT32 *tiltlighting = NULL;
local_for_thread INT32 oldviewwidth = 0;
// dont realloc every frame pls thx
if (tiltlighting == NULL || oldviewwidth != viewwidth)
{
tiltlighting = static_cast<INT32*>(realloc(tiltlighting, sizeof(*tiltlighting) * viewwidth));
oldviewwidth = viewwidth;
}
dest = R_Address(ds->x1, ds->y);
const INT32 stride = vid.width;
// Lighting is simple. It's just linear interpolation from start to end
{
float planelightfloat = PLANELIGHTFLOAT;
float lightstart, lightend;
lightend = (iz + ds->szp.x*width) * planelightfloat;
lightstart = iz * planelightfloat;
R_CalcTiltedLighting(tiltlighting, ds->x1, ds->x2, FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend));
//CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf);
}
do
{
UINT8 *colormap = ds->planezlight[tiltlighting[ds->x1++]] + (ds->colormap - colormaps);
*dest = colormap[*dest];
dest++;
}
while (--width >= 0);
}
+3 -3
View File
@@ -173,7 +173,7 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe
// recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight).
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
// 18/08/18: (No it's actually 16*viewheight, thanks Lactozilla for finding this out)
static void R_SetupFreelook(void)
{
// clip it in the case we are looking a hardware 90 degrees full aiming
@@ -494,8 +494,8 @@ void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj)
interp->polyobj.polyobj = polyobj;
interp->polyobj.vertices_size = polyobj->numVertices;
interp->polyobj.oldvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
interp->polyobj.bakvertices = Z_CallocAlign(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL, 32);
interp->polyobj.oldvertices = Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL);
interp->polyobj.bakvertices = Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL);
for (size_t i = 0; i < polyobj->numVertices; i++)
{
interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ] = polyobj->vertices[i]->x;
+8
View File
@@ -15,6 +15,10 @@
#ifndef __R_FPS_H__
#define __R_FPS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "m_fixed.h"
#include "p_local.h"
#include "r_state.h"
@@ -175,4 +179,8 @@ void R_UpdateMobjInterpolators(void);
void R_ResetMobjInterpolationState(mobj_t *mobj);
void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+8
View File
@@ -14,6 +14,10 @@
#ifndef __R_LOCAL__
#define __R_LOCAL__
#ifdef __cplusplus
extern "C" {
#endif
// Screen size related parameters.
#include "doomdef.h"
@@ -38,4 +42,8 @@ extern drawseg_t *firstseg;
void SplitScreen_OnChange(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __R_LOCAL__
+257 -255
View File
@@ -13,6 +13,8 @@
/// utility functions (BSP, geometry, trigonometry).
/// See tables.c, too.
#include <algorithm>
#include "doomdef.h"
#include "g_game.h"
#include "g_input.h"
@@ -88,7 +90,7 @@ INT32 viewangletox[FINEANGLES/2];
// The xtoviewangleangle[] table maps a screen pixel
// to the lowest viewangle that maps back to x ranges
// from clipangle to -clipangle.
angle_t xtoviewangle[MAXVIDWIDTH+1];
angle_t *xtoviewangle;
lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
lighttable_t *scalelightfixed[MAXLIGHTSCALE];
@@ -100,23 +102,23 @@ extracolormap_t extra_colormaps[MAXCOLORMAPS];
// Performance stats
precise_t ps_prevframetime = 0;
ps_metric_t ps_rendercalltime = {0};
ps_metric_t ps_otherrendertime = {0};
ps_metric_t ps_uitime = {0};
ps_metric_t ps_swaptime = {0};
ps_metric_t ps_rendercalltime = {};
ps_metric_t ps_otherrendertime = {};
ps_metric_t ps_uitime = {};
ps_metric_t ps_swaptime = {};
ps_metric_t ps_skyboxtime = {0};
ps_metric_t ps_bsptime = {0};
ps_metric_t ps_skyboxtime = {};
ps_metric_t ps_bsptime = {};
ps_metric_t ps_sw_spritecliptime = {0};
ps_metric_t ps_sw_portaltime = {0};
ps_metric_t ps_sw_planetime = {0};
ps_metric_t ps_sw_maskedtime = {0};
ps_metric_t ps_sw_spritecliptime = {};
ps_metric_t ps_sw_portaltime = {};
ps_metric_t ps_sw_planetime = {};
ps_metric_t ps_sw_maskedtime = {};
ps_metric_t ps_numbspcalls = {0};
ps_metric_t ps_numsprites = {0};
ps_metric_t ps_numdrawnodes = {0};
ps_metric_t ps_numpolyobjects = {0};
ps_metric_t ps_numbspcalls = {};
ps_metric_t ps_numsprites = {};
ps_metric_t ps_numdrawnodes = {};
ps_metric_t ps_numpolyobjects = {};
static CV_PossibleValue_t drawdist_cons_t[] = {
/*{256, "256"},*/ {512, "512"}, {768, "768"},
@@ -125,16 +127,17 @@ static CV_PossibleValue_t drawdist_cons_t[] = {
{8192, "8192"}, {12288, "12288"}, {20480, "20480"},
{24576, "24576"},{0, "Infinite"}, {0, NULL}};
#if defined(__x86_64__) || defined(__amd64__) || defined(__aarch64__) || defined(__arm64__) // only for 64bit (idk how else to proper check lmao)
#if __SIZEOF_POINTER__ < 8 // only for 64bit
static CV_PossibleValue_t drawdist_precip_cons_t[] = {
{256, "256"}, {512, "512"}, {768, "768"},
{256, "256"}, {512, "512"}, {768, "768"},
{1024, "1024"}, {1536, "1536"}, {2048, "2048"},
{3072, "3072"}, {4096, "4096"}, {0, "None"}, {0, NULL}};
{0, "None"}, {0, NULL}};
#else
static CV_PossibleValue_t drawdist_precip_cons_t[] = {
{256, "256"}, {512, "512"}, {768, "768"},
{1024, "1024"}, {1536, "1536"}, {2048, "2048"},
{0, "None"}, {0, NULL}};
{256, "256"}, {512, "512"}, {768, "768"},
{1024, "1024"}, {1536, "1536"}, {2048, "2048"},
{3072, "3072"}, {4096, "4096"}, {0, "None"}, {0, NULL}};
#endif
static CV_PossibleValue_t maxinterpdist_cons_t[] = {
@@ -156,10 +159,6 @@ static void FlipCam_OnChange(void);
static void FlipCam2_OnChange(void);
static void FlipCam3_OnChange(void);
static void FlipCam4_OnChange(void);
void SendWeaponPref(void);
void SendWeaponPref2(void);
void SendWeaponPref3(void);
void SendWeaponPref4(void);
static void DirLight_OnChange(void);
@@ -184,38 +183,37 @@ consvar_t cv_flipcam[MAXSPLITSCREENPLAYERS] = {
{"flipcam4", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, FlipCam4_OnChange, 0, NULL, NULL, 0, 0, NULL}
};
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ffloorclip = {"r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_spriteclip = {"r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_uncappedhud = {"uncappedhud", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ffloorclip = {"r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_spriteclip = {"r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_softcyancut = {"softwarecyancut", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE|CV_CALL|CV_NOINIT, drawdist_precip_cons_t, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_lessprecip = {"lessweathereffects", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_lessprecip = {"lessweathereffects", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mobjscaleprecip = {"scaleprecipmobjscale", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Precipstuff_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_maxinterpdist = {"maxinterpdist", "Infinite", CV_SAVE, maxinterpdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ripplewater = {"waterripples", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// cap fov, fov too high tears software apart.
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL|CV_SAVE, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fovchange = {"fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_maxinterpdist = {"maxinterpdist", "Infinite", CV_SAVE, maxinterpdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ripplewater = {"waterripples", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// Okay, whoever said homremoval causes a performance hit should be shot.
consvar_t cv_homremoval = {"homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_homremoval = {"homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// cap fov, fov too high tears software apart.
consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL|CV_SAVE, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_fovchange = {"fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// randomized directional lightning
consvar_t cv_randomdirlight = {"randomdirectionallight", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, DirLight_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_randomdirlight = {"randomdirectionallight", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, DirLight_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_uncappedhud = {"uncappedhud", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
// tells to reset the maplight at next map change
static void DirLight_OnChange(void)
@@ -493,7 +491,7 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
// Returns search dimensions within a blockmap, in the direction of viewangle and out to a certain distance.
void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32 *yl, INT32 *yh)
{
const angle_t left = viewangle - clipangle;
const angle_t left = viewangle - clipangle;
const angle_t right = viewangle + clipangle;
const fixed_t vxleft = viewx + FixedMul(drawdist, FCOS(left));
@@ -503,10 +501,10 @@ void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32
const fixed_t vyright = viewy + FixedMul(drawdist, FSIN(right));
// Try to narrow the search to within only the field of view
*xl = (unsigned)(min(viewx, min(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
*xh = (unsigned)(max(viewx, max(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
*yl = (unsigned)(min(viewy, min(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
*yh = (unsigned)(max(viewy, max(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
*xl = (unsigned)(std::min(viewx, std::min(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
*xh = (unsigned)(std::max(viewx, std::max(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
*yl = (unsigned)(std::min(viewy, std::min(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
*yh = (unsigned)(std::max(viewy, std::max(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
if (*xh >= bmapwidth)
*xh = bmapwidth - 1;
@@ -630,7 +628,7 @@ static struct {
INT32 scrmapsize;
INT32 x1; // clip rendering horizontally for efficiency
INT16 ceilingclip[MAXVIDWIDTH], floorclip[MAXVIDWIDTH];
INT16 *ceilingclip, *floorclip;
boolean use;
} viewmorph = {
@@ -641,7 +639,7 @@ static struct {
0,
0,
{}, {},
NULL, NULL,
false
};
@@ -659,7 +657,6 @@ void R_CheckViewMorph(void)
rollangle >>= ANGLETOFINESHIFT;
rollangle = ((rollangle+2) & ~3) & FINEMASK; // Limit the distinct number of angles to reduce recalcs from angles changing a lot.
if (rollangle == viewmorph.rollangle &&
viewmorph.scrmapsize == vid.width*vid.height)
return; // No change
@@ -679,10 +676,10 @@ void R_CheckViewMorph(void)
if (viewmorph.scrmapsize != vid.width*vid.height)
{
if (viewmorph.scrmap)
free(viewmorph.scrmap);
viewmorph.scrmap = malloc(vid.width*vid.height * sizeof(INT32));
viewmorph.scrmapsize = vid.width*vid.height;
viewmorph.scrmap = static_cast<INT32*>(realloc(viewmorph.scrmap, vid.width*vid.height * sizeof(INT32)));
viewmorph.ceilingclip = static_cast<INT16*>(realloc(viewmorph.ceilingclip, vid.width * sizeof(INT16)));
viewmorph.floorclip = static_cast<INT16*>(realloc(viewmorph.floorclip, vid.width * sizeof(INT16)));
}
temp = FINECOSINE(rollangle);
@@ -694,7 +691,7 @@ void R_CheckViewMorph(void)
x1 = (vid.width*fabsf(rollcos) + vid.height*fabsf(rollsin)) / vid.width;
y1 = (vid.height*fabsf(rollcos) + vid.width*fabsf(rollsin)) / vid.height;
temp = max(x1, y1)*FRACUNIT;
temp = std::max(x1, y1)*FRACUNIT;
if (temp < FRACUNIT)
temp = FRACUNIT;
else
@@ -740,10 +737,10 @@ void R_CheckViewMorph(void)
xb = vid.width-1-xa;
yb = vid.height-1-ya;
viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya);
viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya);
viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb);
viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb);
viewmorph.ceilingclip[xa] = std::min(viewmorph.ceilingclip[xa], ya);
viewmorph.floorclip[xa] = std::max(viewmorph.floorclip[xa], ya);
viewmorph.ceilingclip[xb] = std::min(viewmorph.ceilingclip[xb], yb);
viewmorph.floorclip[xb] = std::max(viewmorph.floorclip[xb], yb);
x2 += rollcos;
y2 += rollsin;
}
@@ -757,10 +754,10 @@ void R_CheckViewMorph(void)
xb = vid.width-1-xa;
yb = vid.height-1-ya;
viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya);
viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya);
viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb);
viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb);
viewmorph.ceilingclip[xa] = std::min(viewmorph.ceilingclip[xa], ya);
viewmorph.floorclip[xa] = std::max(viewmorph.floorclip[xa], ya);
viewmorph.ceilingclip[xb] = std::min(viewmorph.ceilingclip[xb], yb);
viewmorph.floorclip[xb] = std::max(viewmorph.floorclip[xb], yb);
x2 -= rollsin;
y2 += rollcos;
}
@@ -798,8 +795,8 @@ void R_CheckViewMorph(void)
void R_ApplyViewMorph(void)
{
UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0];
UINT8 *tmpscr = vid.screens[4];
UINT8 *srcscr = vid.screens[0];
INT32 p, end = vid.width * vid.height;
if (!viewmorph.use)
@@ -834,8 +831,7 @@ void R_ApplyViewMorph(void)
for (p = 0; p < end; p++)
tmpscr[p] = srcscr[viewmorph.scrmap[p]];
VID_BlitLinearScreen(tmpscr, screens[0],
vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.width);
VID_BlitLinearScreen(tmpscr, vid.screens[0], vid.width, vid.height, vid.width, vid.width);
}
angle_t R_ViewRollAngle(const player_t *player)
@@ -888,6 +884,8 @@ void R_SetViewSize(void)
setsizeneeded = true;
}
static void R_SetupViewBuffers(void);
//
// R_ExecuteSetViewSize
//
@@ -906,18 +904,15 @@ void R_ExecuteSetViewSize(void)
// status bar overlay
st_overlay = cv_showhud.value;
scaledviewwidth = vid.width;
viewwidth = vid.width;
viewheight = vid.height;
if (splitscreen)
viewheight >>= 1;
viewwidth = scaledviewwidth;
if (splitscreen > 1)
{
viewwidth >>= 1;
scaledviewwidth >>= 1;
}
centerx = viewwidth/2;
@@ -925,9 +920,7 @@ void R_ExecuteSetViewSize(void)
centerxfrac = centerx<<FRACBITS;
centeryfrac = centery<<FRACBITS;
R_SetFov(cv_fov.value);
R_InitViewBuffer(scaledviewwidth, viewheight);
R_SetupViewBuffers();
// why did we calc all the software crap?
#ifdef HWRENDER
@@ -941,7 +934,10 @@ void R_ExecuteSetViewSize(void)
// thing clipping
for (i = 0; i < viewwidth; i++)
{
negonearray[i] = -1;
screenheightarray[i] = (INT16)viewheight;
}
if (ds_su)
Z_Free(ds_su);
@@ -951,7 +947,6 @@ void R_ExecuteSetViewSize(void)
Z_Free(ds_sz);
ds_su = ds_sv = ds_sz = NULL;
ds_sup = ds_svp = ds_szp = NULL;
memset(scalelight, 0xFF, sizeof(scalelight));
@@ -979,33 +974,52 @@ void R_ExecuteSetViewSize(void)
fixed_t R_GetPlayerFov(player_t *player)
{
fixed_t fov = cv_fov.value + player->fovadd;
return max(MINFOV*FRACUNIT, min(fov, MAXFOV*FRACUNIT));
return std::max(MINFOV*FRACUNIT, std::min(fov, MAXFOV*FRACUNIT));
}
static void R_SetFov(fixed_t playerfov)
static void R_CalcFov(fixed_t playerfov)
{
angle_t fov = FixedAngle(playerfov/2) + ANGLE_90;
fovtan = FixedMul(FINETANGENT(fov >> ANGLETOFINESHIFT), viewmorph.zoomneeded);
if (splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view
fovtan = 17*fovtan/10;
// this is only used for planes rendering in software mode
INT32 j = viewheight*16;
for (INT32 i = 0; i < j; i++)
{
fixed_t dy = (i - viewheight*8)<<FRACBITS;
dy = FixedMul(abs(dy), fovtan);
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
}
projection = projectiony = FixedDiv(centerxfrac, fovtan);
}
static void R_InitViewMapping(void)
{
R_InitTextureMapping();
if (rendermode == render_soft)
{
// this is only used for planes rendering in software mode
INT32 j = viewheight*16;
for (INT32 i = 0; i < j; i++)
{
fixed_t dy = (i - viewheight*8)<<FRACBITS;
dy = FixedMul(abs(dy), fovtan);
yslopetab[i] = FixedDiv(centerx*FRACUNIT, dy);
}
}
// setup sky scaling
R_SetSkyScale();
}
static void R_SetupViewBuffers(void)
{
R_CalcFov(cv_fov.value);
R_InitViewBuffer(viewwidth, viewheight);
R_InitViewMapping();
}
static void R_SetFov(fixed_t playerfov)
{
R_CalcFov(playerfov);
R_InitViewMapping();
}
//
// R_Init
@@ -1021,9 +1035,6 @@ void R_Init(void)
R_InitViewBorder();
R_SetViewSize(); // setsizeneeded is set true
//I_OutputMsg("\nR_InitPlanes");
R_InitPlanes();
// this is now done by SCR_Recalc() at the first mode set
//I_OutputMsg("\nR_InitLightTables");
R_InitLightTables();
@@ -1062,33 +1073,93 @@ static void R_SetupCommonFrame(player_t * player, sector_t * sector)
static void R_SetupAimingFrame(player_t *player, camera_t *thiscam)
{
if (player->awayviewtics)
if (player->awayviewtics && player->awayviewmobj)
{
newview->aim = player->awayviewaiming;
newview->angle = player->awayviewmobj->angle;
}
else if (thiscam->chase)
else if (thiscam && thiscam->chase)
{
newview->aim = thiscam->aiming;
newview->angle = thiscam->angle;
}
else if (P_IsLocalPlayer(player) && !demo.playback && player->playerstate != PST_DEAD)
{
newview->aim = localaiming[viewssnum];
newview->angle = localangle[viewssnum];
}
else
{
newview->aim = player->aiming;
newview->angle = player->mo->angle;
}
}
if (!demo.playback && player->playerstate != PST_DEAD)
static void R_SetupSkyScale(player_t *player, camera_t *thiscam, mapheader_t *mh)
{
if (!mh->skybox_scalex && !mh->skybox_scaley && !mh->skybox_scalez)
return;
auto setup_skyscale = [&](fixed_t mox, fixed_t moy, fixed_t zscale)
{
if (skyboxmo[1])
{
for (UINT8 i = 0; i <= splitscreen; i++)
angle_t ang;
fixed_t x = 0, y = 0;
if (mh->skybox_scalex > 0)
x = (mox - skyboxmo[1]->x) / mh->skybox_scalex;
else if (mh->skybox_scalex < 0)
x = (mox - skyboxmo[1]->x) * -mh->skybox_scalex;
if (mh->skybox_scaley > 0)
y = (moy - skyboxmo[1]->y) / mh->skybox_scaley;
else if (mh->skybox_scaley < 0)
y = (moy - skyboxmo[1]->y) * -mh->skybox_scaley;
switch (viewmobj->angle)
{
if (player == (i == 0 ? &players[consoleplayer] : &players[displayplayers[i]]))
{
newview->angle = localangle[i];
newview->aim = localaiming[i];
case 0:
newview->x += x;
newview->y += y;
break;
case ANGLE_90:
newview->x -= y;
newview->y += x;
break;
case ANGLE_180:
newview->x -= x;
newview->y -= y;
break;
case ANGLE_270:
newview->x += y;
newview->y -= x;
break;
default:
ang = viewmobj->angle>>ANGLETOFINESHIFT;
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
break;
}
}
}
if (mh->skybox_scalez > 0)
newview->z += zscale / mh->skybox_scalez;
else if (mh->skybox_scalez < 0)
newview->z += zscale * -mh->skybox_scalez;
};
if (player->awayviewtics && player->awayviewmobj)
{
setup_skyscale(player->awayviewmobj->x, player->awayviewmobj->y, (player->awayviewmobj->z + 20*FRACUNIT));
}
else if (thiscam && thiscam->chase)
{
setup_skyscale(thiscam->x, thiscam->y, (thiscam->z + (thiscam->height>>1)));
}
else
{
setup_skyscale(player->mo->x, player->mo->y, player->viewz);
}
}
@@ -1097,12 +1168,14 @@ void R_SkyboxFrame(int s)
player_t *player = &players[displayplayers[s]];
camera_t *thiscam = &camera[s];
subsector_t * subsector = NULL;
mapheader_t *mh = mapheaderinfo[gamemap-1];
R_SetViewContext(VIEWCONTEXT_SKY1 + s);
R_SetViewContext(static_cast<viewcontext_e>(VIEWCONTEXT_SKY1 + s));
// cut-away view stuff
newview->sky = true;
viewmobj = skyboxmo[0];
#ifdef PARANOIA
if (P_MobjWasRemoved(viewmobj))
{
@@ -1110,78 +1183,19 @@ void R_SkyboxFrame(int s)
I_Error("R_SkyboxFrame: viewmobj null (player %s)", sizeu1(playeri));
}
#endif
R_SetupAimingFrame(player, thiscam);
newview->angle += viewmobj->angle;
newview->x = viewmobj->x;
newview->y = viewmobj->y;
newview->z = 0;
if (viewmobj->spawnpoint)
newview->z = ((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS;
newview->z = (viewmobj->spawnpoint) ? (((fixed_t)viewmobj->spawnpoint->angle)<<FRACBITS) : 0;
#define SETUPSKYVIEW(viewmo, zscale)\
if (skyboxmo[1])\
{\
fixed_t x = 0, y = 0;\
if (mh->skybox_scalex > 0)\
x = (viewmo->x - skyboxmo[1]->x) / mh->skybox_scalex;\
else if (mh->skybox_scalex < 0)\
x = (viewmo->x - skyboxmo[1]->x) * -mh->skybox_scalex;\
if (mh->skybox_scaley > 0)\
y = (viewmo->y - skyboxmo[1]->y) / mh->skybox_scaley;\
else if (mh->skybox_scaley < 0)\
y = (viewmo->y - skyboxmo[1]->y) * -mh->skybox_scaley;\
if (viewmobj->angle == 0)\
{\
newview->x += x;\
newview->y += y;\
}\
else if (viewmobj->angle == ANGLE_90)\
{\
newview->x -= y;\
newview->y += x;\
}\
else if (viewmobj->angle == ANGLE_180)\
{\
newview->x -= x;\
newview->y -= y;\
}\
else if (viewmobj->angle == ANGLE_270)\
{\
newview->x += y;\
newview->y -= x;\
}\
else\
{\
angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;\
newview->x += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));\
newview->y += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));\
}\
}\
if (mh->skybox_scalez > 0)\
newview->z += zscale / mh->skybox_scalez;\
else if (mh->skybox_scalez < 0)\
newview->z += zscale * -mh->skybox_scalez;
if (mapheaderinfo[gamemap-1])
if (mh)
{
mapheader_t *mh = mapheaderinfo[gamemap-1];
if (player->awayviewtics)
{
SETUPSKYVIEW(player->awayviewmobj, (player->awayviewmobj->z + 20*FRACUNIT));
}
else if (thiscam->chase)
{
SETUPSKYVIEW(thiscam, (thiscam->z + (thiscam->height>>1)));
}
else
{
SETUPSKYVIEW(player->mo, player->viewz);
}
R_SetupSkyScale(player, thiscam, mh);
}
#undef SETUPSKYVIEW
if (!P_MobjWasRemoved(viewmobj) && viewmobj->subsector && viewmobj->subsector->sector)
subsector = viewmobj->subsector;
@@ -1196,7 +1210,8 @@ void R_SetupFrame(int s, boolean skybox)
boolean chasecam = (cv_chasecam[s].value);
sector_t * sector = NULL;
R_SetViewContext(VIEWCONTEXT_PLAYER1 + s);
R_SetViewContext(static_cast<viewcontext_e>(VIEWCONTEXT_PLAYER1 + s));
if (thiscam->reset)
{
R_ResetViewInterpolation(s);
@@ -1225,7 +1240,7 @@ void R_SetupFrame(int s, boolean skybox)
R_SetupAimingFrame(player, thiscam);
if (player->awayviewtics) // cut-away view stuff
if (player->awayviewtics && player->awayviewmobj) // cut-away view stuff
{
viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN
I_Assert(viewmobj != NULL);
@@ -1234,7 +1249,7 @@ void R_SetupFrame(int s, boolean skybox)
newview->y = viewmobj->y;
newview->z = viewmobj->z + 20*FRACUNIT;
if (!P_MobjWasRemoved(viewmobj) && viewmobj->subsector && viewmobj->subsector->sector)
if (viewmobj->subsector && viewmobj->subsector->sector)
sector = viewmobj->subsector->sector;
R_SetupCommonFrame(player, sector);
@@ -1242,17 +1257,18 @@ void R_SetupFrame(int s, boolean skybox)
else if (thiscam && chasecam) // use outside cam view
{
viewmobj = NULL;
I_Assert(thiscam != NULL);
newview->x = thiscam->x;
newview->y = thiscam->y;
newview->z = thiscam->z + (thiscam->height>>1);
if (thiscam != NULL && thiscam->subsector && thiscam->subsector->sector)
if (thiscam->subsector && thiscam->subsector->sector)
sector = thiscam->subsector->sector;
R_SetupCommonFrame(player, sector);
}
else // use the player's eyes view
else if (player->mo) // use the player's eyes view
{
viewmobj = player->mo;
I_Assert(viewmobj != NULL);
@@ -1261,7 +1277,7 @@ void R_SetupFrame(int s, boolean skybox)
newview->y = viewmobj->y;
newview->z = player->viewz;
if (!P_MobjWasRemoved(viewmobj) && viewmobj->subsector && viewmobj->subsector->sector)
if (viewmobj->subsector && viewmobj->subsector->sector)
sector = viewmobj->subsector->sector;
R_SetupCommonFrame(player, sector);
@@ -1275,8 +1291,8 @@ static void R_PortalFrame(portal_t *portal)
viewz = portal->viewz;
viewangle = portal->viewangle;
// viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
// viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
//viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
//viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
portalclipstart = portal->start;
portalclipend = portal->end;
@@ -1284,8 +1300,7 @@ static void R_PortalFrame(portal_t *portal)
if (portal->clipline != -1)
{
portalclipline = &lines[portal->clipline];
portalcullsector = portalclipline->frontsector;
viewsector = portalclipline->frontsector;
viewsector = portalcullsector = portalclipline->frontsector;
}
else
{
@@ -1295,10 +1310,41 @@ static void R_PortalFrame(portal_t *portal)
}
}
static void Mask_Pre (maskcount_t* m)
{
m->drawsegs[0] = ds_p - drawsegs;
m->vissprites[0] = visspritecount;
m->viewx = viewx;
m->viewy = viewy;
m->viewz = viewz;
m->viewsector = viewsector;
}
static void Mask_Post (maskcount_t* m)
{
m->drawsegs[1] = ds_p - drawsegs;
m->vissprites[1] = visspritecount;
}
// ================
// R_RenderView
// ================
// viewx, viewy, viewangle, all that good stuff must be set
static void R_RenderViewpoint(maskcount_t* mask, boolean drawprecip)
{
Mask_Pre(mask);
curdrawsegs = ds_p;
R_RenderBSPNode((INT32)numnodes - 1);
if (drawprecip)
R_AddPrecipitationSprites();
Mask_Post(mask);
}
// FAB NOTE FOR WIN32 PORT !! I'm not finished already,
// but I suspect network may have problems with the video buffer being locked
// for all duration of rendering, and being released only once at the end..
@@ -1309,52 +1355,19 @@ static fixed_t viewfov[MAXSPLITSCREENPLAYERS];
void R_RenderPlayerView(player_t *player)
{
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
UINT8 i;
// if this is display player 1
if (cv_homremoval.value && player == &players[displayplayers[0]])
{
if (cv_homremoval.value == 1)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // No HOM effect!
else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 128+(timeinmap&15));
}
// Draw over the fourth screen so you don't have to stare at a HOM :V
else if (splitscreen == 2 && player == &players[displayplayers[2]])
{
// V_DrawPatchFill, but for the fourth screen only
patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE);
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz;
for (x = vid.width>>1; x < vid.width; x += pw)
{
for (y = vid.height>>1; y < vid.height; y += ph)
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
}
}
INT32 nummasks = 1;
maskcount_t* masks = static_cast<maskcount_t*>(malloc(sizeof(maskcount_t)));
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
// load previous saved value of skyVisible for the player
for (i = 0; i <= splitscreen; i++)
skyVisible = skyVisiblePerPlayer[viewssnum];
const fixed_t fov = R_GetPlayerFov(player);
if (viewfov[viewssnum] != fov)
{
if (player != &players[displayplayers[i]])
continue;
skyVisible = skyVisiblePerPlayer[i];
break;
}
fixed_t fov = R_GetPlayerFov(player);
for (UINT8 j = 0; j <= splitscreen; j++)
{
if (player == &players[displayplayers[i]]
&& viewfov[i] != fov)
{
viewfov[i] = fov;
R_SetFov(fov);
}
viewfov[viewssnum] = fov;
R_SetFov(fov);
}
Portal_InitList();
@@ -1368,17 +1381,13 @@ void R_RenderPlayerView(player_t *player)
R_ClearDrawSegs();
R_ClearPlanes();
R_ClearSprites();
#ifdef FLOORSPLATS
R_ClearVisibleFloorSplats();
#endif
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
R_RenderViewpoint(&masks[nummasks - 1], false);
R_ClipSprites(drawsegs, NULL);
R_DrawSkyPlanes(); // draw the fucker again to prevent some artifacts
R_DrawPlanes();
#ifdef FLOORSPLATS
R_DrawVisibleFloorSplats();
#endif
R_DrawMasked();
R_DrawMasked(masks, nummasks);
}
PS_STOP_TIMING(ps_skyboxtime);
@@ -1405,22 +1414,16 @@ void R_RenderPlayerView(player_t *player)
}
R_ClearDrawSegs();
R_ClearSprites();
#ifdef FLOORSPLATS
R_ClearVisibleFloorSplats();
#endif
// check for new console commands.
NetUpdate();
// The head node is the last node output.
ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
PS_START_TIMING(ps_bsptime);
R_RenderBSPNode((INT32)numnodes - 1);
R_RenderViewpoint(&masks[nummasks - 1], true);
PS_STOP_TIMING(ps_bsptime);
R_AddPrecipitationSprites();
PS_START_TIMING(ps_sw_spritecliptime);
R_ClipSprites();
R_ClipSprites(drawsegs, NULL);
PS_STOP_TIMING(ps_sw_spritecliptime);
ps_numsprites.value.i = numvisiblesprites;
@@ -1449,43 +1452,40 @@ void R_RenderPlayerView(player_t *player)
// that were previously stored.
Portal_ClipApply(portal);
validcount++;
masks = static_cast<maskcount_t*>(realloc(masks, (++nummasks)*sizeof(maskcount_t)));
// Render the BSP from the new viewpoint, and clip
// any sprites with the new clipsegs and window.
R_RenderBSPNode((INT32)numnodes - 1);
R_ClipSprites();
R_RenderViewpoint(&masks[nummasks - 1], true);
R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal);
Portal_Remove(portal);
validcount++;
}
}
PS_STOP_TIMING(ps_sw_portaltime);
PS_START_TIMING(ps_sw_planetime);
if (!skybox)
R_DrawSkyPlanes();
R_DrawPlanes();
PS_STOP_TIMING(ps_sw_planetime);
#ifdef FLOORSPLATS
R_DrawVisibleFloorSplats();
#endif
// draw mid texture and sprite
// And now 3D floors/sides!
PS_START_TIMING(ps_sw_maskedtime);
R_DrawMasked();
R_DrawMasked(masks, nummasks);
PS_STOP_TIMING(ps_sw_maskedtime);
free(masks);
// Check for new console commands.
NetUpdate();
// save value to skyVisiblePerPlayer
// this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa
for (i = 0; i <= splitscreen; i++)
{
if (player != &players[displayplayers[i]])
continue;
skyVisiblePerPlayer[i] = skyVisible;
break;
}
skyVisiblePerPlayer[viewssnum] = skyVisible;
}
// =========================================================================
@@ -1526,11 +1526,13 @@ void R_RegisterEngineStuff(void)
{
CV_RegisterVar(&cv_chasecam[i]);
}
CV_RegisterVar(&cv_shadow);
CV_RegisterVar(&cv_shadowoffs);
CV_RegisterVar(&cv_skybox);
CV_RegisterVar(&cv_ffloorclip);
CV_RegisterVar(&cv_spriteclip);
CV_RegisterVar(&cv_softcyancut);
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
+11 -1
View File
@@ -14,6 +14,10 @@
#ifndef __R_MAIN__
#define __R_MAIN__
#ifdef __cplusplus
extern "C" {
#endif
#include "d_player.h"
#include "r_data.h"
#include "m_perfstats.h"
@@ -84,7 +88,7 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
//
// killough 5/2/98: reformatted
//
FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *restrict node)
FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t * restrict node)
{
if (!node->dx)
return x <= node->x ? node->dy > 0 : node->dy < 0;
@@ -207,6 +211,7 @@ extern consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_flipcam[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_shadow, cv_shadowoffs;
extern consvar_t cv_ffloorclip, cv_spriteclip;
extern consvar_t cv_softcyancut;
extern consvar_t cv_translucency;
extern consvar_t cv_drawdist, cv_drawdist_precip, cv_lessprecip, cv_mobjscaleprecip;
extern consvar_t cv_fov, cv_fovchange;
@@ -245,4 +250,9 @@ void R_RegisterEngineStuff(void);
INT32 R_GetHudUncap(void);
// same as above but keeps interpolation during pause
INT32 R_GetMenuUncap(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif
+1
View File
@@ -16,6 +16,7 @@
#include "doomdef.h"
#include "r_patch.h"
#include "r_things.h"
#include "r_skins.h"
#include "z_zone.h"
#include "w_wad.h"
+8
View File
@@ -12,6 +12,10 @@
#ifndef __R_PATCHROTATION__
#define __R_PATCHROTATION__
#ifdef __cplusplus
extern "C" {
#endif
#include "r_fps.h"
// Sprite rotation
@@ -27,4 +31,8 @@ extern fixed_t rollcosang[ROTANGLES];
extern fixed_t rollsinang[ROTANGLES];
#endif
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __R_PATCHROTATION__
-1201
View File
File diff suppressed because it is too large. Load diff
+1408
View File
File diff suppressed because it is too large. Load diff
+21 -19
View File
@@ -14,6 +14,10 @@
#ifndef __R_PLANE__
#define __R_PLANE__
#ifdef __cplusplus
extern "C" {
#endif
#include "screen.h" // needs MAXVIDWIDTH/MAXVIDHEIGHT
#include "r_data.h"
#include "p_polyobj.h"
@@ -43,9 +47,8 @@ typedef struct visplane_s
// colormaps per sector
extracolormap_t *extra_colormap;
// leave pads for [minx-1]/[maxx+1]
UINT16 padtopstart, top[MAXVIDWIDTH], padtopend;
UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend;
UINT16 *top, *top_memory;
UINT16 *bottom, *bottom_memory;
INT32 high, low; // R_PlaneBounds should set these.
fixed_t xoffs, yoffs; // Scrolling flats.
@@ -55,8 +58,11 @@ typedef struct visplane_s
pslope_t *slope;
boolean noencore;
boolean cyan;
} visplane_t;
extern visplane_t *visplanes[MAXVISPLANES];
extern visplane_t *floorplane;
extern visplane_t *ceilingplane;
@@ -64,25 +70,19 @@ extern visplane_t *ceilingplane;
extern INT16 *lastopening, *openings;
extern size_t maxopenings;
extern INT16 floorclip[MAXVIDWIDTH], ceilingclip[MAXVIDWIDTH];
extern fixed_t frontscale[MAXVIDWIDTH], yslopetab[MAXVIDHEIGHT*16];
extern fixed_t cachedheight[MAXVIDHEIGHT];
extern fixed_t cacheddistance[MAXVIDHEIGHT];
extern fixed_t cachedxstep[MAXVIDHEIGHT];
extern fixed_t cachedystep[MAXVIDHEIGHT];
extern INT16 *floorclip, *ceilingclip;
extern fixed_t *frontscale, *yslopetab;
extern fixed_t basexscale, baseyscale;
extern fixed_t *yslope;
extern lighttable_t **planezlight;
void R_InitPlanes(void);
void R_AllocPlaneMemory(void);
void R_ClearPlanes(void);
void R_ClearFFloorClips (void);
void R_MapPlane(INT32 y, INT32 x1, INT32 x2);
void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2);
void R_DrawSkyPlanes(void);
void R_DrawPlanes(void);
void R_CalculateSlopeVectors(pslope_t *slope, fixed_t planeviewx, fixed_t planeviewy, fixed_t planeviewz, fixed_t planexscale, fixed_t planeyscale, fixed_t planexoffset, fixed_t planeyoffset, angle_t planeviewangle, angle_t planeangle, float fudge);
visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle,
extracolormap_t *planecolormap, ffloor_t *ffloor
, polyobj_t *polyobj
@@ -93,9 +93,6 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
void R_PlaneBounds(visplane_t *plane);
// Draws a single visplane.
void R_DrawSinglePlane(visplane_t *pl);
typedef struct planemgr_s
{
visplane_t *plane;
@@ -104,8 +101,8 @@ typedef struct planemgr_s
fixed_t b_pos; // B for Back sector
fixed_t f_frac, f_step;
fixed_t b_frac, b_step;
INT16 f_clip[MAXVIDWIDTH];
INT16 c_clip[MAXVIDWIDTH];
INT16 *f_clip;
INT16 *c_clip;
// For slope rendering; the height at the other end
fixed_t f_pos_slope;
@@ -119,4 +116,9 @@ typedef struct planemgr_s
extern visffloor_t ffloor[MAXFFLOORS];
extern INT32 numffloors;
#ifdef __cplusplus
} // extern "C"
#endif
#endif
Loaded 100 of 132 files, more files were not shown because too many files have changed in this diff. Show more