summaryrefslogtreecommitdiffstats
path: root/apps/plugins/sdl/progs
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2017-01-21 15:18:31 -0500
committerFranklin Wei <git@fwei.tk>2017-12-23 21:01:26 -0500
commita855d6202536ff28e5aae4f22a0f31d8f5b325d0 (patch)
tree8c75f224dd64ed360505afa8843d016b0d75000b /apps/plugins/sdl/progs
parent01c6dcf6c7b9bb1ad2fa0450f99bacc5f3d3e04b (diff)
downloadrockbox-a855d6202536ff28e5aae4f22a0f31d8f5b325d0.tar.gz
rockbox-a855d6202536ff28e5aae4f22a0f31d8f5b325d0.zip
Port of Duke Nukem 3D
This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL for Rockbox. Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9
Diffstat (limited to 'apps/plugins/sdl/progs')
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/Makefile693
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/Makefile.am3
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/Makefile.in693
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/build.h320
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/cache.c225
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/cache.h34
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/display.c1949
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/display.h110
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/draw.c919
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/draw.h105
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/dummy_multi.c16
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/ChangeLog177
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/LICENSE7
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/README15
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/callbacks.h27
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/enet.h592
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/list.h43
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/protocol.h198
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/time.h18
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/types.h13
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/unix.h40
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/utility.h12
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/win32.h57
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/engine.c9349
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/engine.h164
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/filesystem.c877
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/filesystem.h49
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/fixedPoint_math.c54
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/fixedPoint_math.h167
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/icon.c168
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/icon.h5
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/macos_compat.h62
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/mmulti.c1707
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/mmulti.cpp1213
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/mmulti_stable.cpp1211
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/mmulti_stable.h19
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/mmulti_unstable.h19
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/multi.c1176
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/network.c222
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/network.h33
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/platform.h38
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/rockbox_compat.h67
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/tiles.c386
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/tiles.h73
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/unix_compat.h67
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/win32_compat.h106
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/windows/inttypes.h305
-rw-r--r--apps/plugins/sdl/progs/duke3d/Engine/src/windows/stdint.h247
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/DbgHelp.h2437
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/Makefile942
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/Makefile.am14
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/Makefile.in942
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/_functio.h174
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/_rts.h54
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/actors.c7157
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/animlib.c352
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/animlib.h155
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/Makefile546
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/Makefile.am4
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/Makefile.in546
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/_al_midi.h174
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/_blaster.h133
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/_guswave.h164
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/_midi.h290
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/_multivc.h318
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/_pas16.h250
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/_sndscap.h136
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/adlibfx.c552
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/adlibfx.h80
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/al_midi.c1510
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/al_midi.h58
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/assert.h49
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/awe32.c540
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/awe32.h58
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/blaster.c2330
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/blaster.h148
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/ctaweapi.h352
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/debugio.c251
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/debugio.h30
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/dma.c379
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/dma.h83
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/dpmi.c250
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/dpmi.h86
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/dsl.c231
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/dsl.h28
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/fx_man.c1058
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/fx_man.h140
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/gmtimbre.c290
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/gus.c283
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/gusmidi.c561
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/gusmidi.h59
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/guswave.c1773
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/guswave.h75
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/interrup.h50
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/irq.c325
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/irq.h54
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/leetimbr.c290
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/linklist.h118
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/ll_man.c173
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/ll_man.h76
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/memcheck.h20
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/midi.c2265
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/midi.h98
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mpu401.c451
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mpu401.h61
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/multivoc.c3404
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/multivoc.h130
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/music.c1035
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/music.h99
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mv_mix.asm505
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mv_mix.c483
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mv_mix16.asm524
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mvreverb.asm181
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mvreverb.c312
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/myprint.c310
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/myprint.h43
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/newgf1.h431
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/nodpmi.c166
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/nomusic.c115
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/pas16.c1924
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/pas16.h81
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/pitch.c258
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/pitch.h47
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/sndcards.h55
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/sndscape.c1661
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/sndscape.h73
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/sndsrc.c658
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/sndsrc.h70
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/standard.h72
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/task_man.c976
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/task_man.h68
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/user.c100
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/user.h38
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/usrhooks.c84
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/usrhooks.h57
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/audiolib/util.h13
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/config.c897
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/config.h46
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/console.c630
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/console.h19
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/control.c930
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/control.h265
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/cvar_defs.c357
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/cvar_defs.h43
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/cvars.c53
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/cvars.h29
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/develop.h65
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/duke3d.h695
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/dukerockbox.h94
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/dukeunix.h100
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/dukewin.h86
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/dummy_audiolib.c215
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/file_lib.h260
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/funct.h593
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/function.h106
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/game.c10966
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/game.h8
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/gamedef.c3316
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/gamedefs.h131
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/global.c931
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/global.h80
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/joystick.h19
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/keyboard.c441
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/keyboard.h224
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/menues.c4707
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/midi/sdl_midi.c191
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/mouse.h51
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/names.h754
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/player.c4462
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/premap.c1728
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/premap.h17
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/rts.c240
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/rts.h84
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/scriplib.c1065
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/scriplib.h373
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/sector.c3249
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/sounddebugdefs.h8
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/soundefs.h1233
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/sounds.c681
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/sounds.h62
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/types.h101
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/util_lib.h77
182 files changed, 108728 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/Makefile b/apps/plugins/sdl/progs/duke3d/Engine/src/Makefile
new file mode 100644
index 0000000000..c70fbde47c
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/Makefile
@@ -0,0 +1,693 @@
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
+# Engine/src/Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/chocolate-duke3d
+pkgincludedir = $(includedir)/chocolate-duke3d
+pkglibdir = $(libdir)/chocolate-duke3d
+pkglibexecdir = $(libexecdir)/chocolate-duke3d
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = Engine/src
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_$(V))
+am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY))
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libEngine_a_AR = $(AR) $(ARFLAGS)
+libEngine_a_LIBADD =
+am_libEngine_a_OBJECTS = libEngine_a-cache.$(OBJEXT) \
+ libEngine_a-display.$(OBJEXT) libEngine_a-draw.$(OBJEXT) \
+ libEngine_a-dummy_multi.$(OBJEXT) libEngine_a-engine.$(OBJEXT) \
+ libEngine_a-filesystem.$(OBJEXT) \
+ libEngine_a-fixedPoint_math.$(OBJEXT) \
+ libEngine_a-mmulti.$(OBJEXT) libEngine_a-network.$(OBJEXT) \
+ libEngine_a-tiles.$(OBJEXT)
+libEngine_a_OBJECTS = $(am_libEngine_a_OBJECTS)
+AM_V_P = $(am__v_P_$(V))
+am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+am__v_lt_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libEngine_a_SOURCES)
+DIST_SOURCES = $(libEngine_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(top_srcdir)/build-aux/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /home/franklin/chocolate_duke3D/build-aux/missing aclocal-1.15
+AMTAR = $${TAR-tar}
+AM_DEFAULT_VERBOSITY = 0
+AUTOCONF = ${SHELL} /home/franklin/chocolate_duke3D/build-aux/missing autoconf
+AUTOHEADER = ${SHELL} /home/franklin/chocolate_duke3D/build-aux/missing autoheader
+AUTOMAKE = ${SHELL} /home/franklin/chocolate_duke3D/build-aux/missing automake-1.15
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -Wall -Wno-pointer-sign -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -Wno-parentheses -Wno-maybe-uninitialized -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-result -fno-strict-aliasing -fno-aggressive-loop-optimizations -DPLATFORM_UNIX -D_GNU_SOURCE=1 -D_REENTRANT -I/usr/include/SDL -g -O2
+CPP = gcc -E
+CPPFLAGS =
+CYGPATH_W = echo
+DEFS = -DPACKAGE_NAME=\"Chocolate\ Duke3D\" -DPACKAGE_TARNAME=\"chocolate-duke3d\" -DPACKAGE_VERSION=\"1.0\" -DPACKAGE_STRING=\"Chocolate\ Duke3D\ 1.0\" -DPACKAGE_BUGREPORT=\"https://github.com/fabiensanglard/chocolate_duke3D/issues\" -DPACKAGE_URL=\"\" -DPACKAGE=\"chocolate-duke3d\" -DVERSION=\"1.0\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_ASSERT_H=1 -DHAVE_ENET_ENET_H=1
+DEPDIR = .deps
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = /usr/bin/grep -E
+EXEEXT =
+GREP = /usr/bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS = -lSDL -lpthread -lSDL_mixer -lSDL -lpthread
+LIBOBJS =
+LIBS =
+LTLIBOBJS =
+MAKEINFO = ${SHELL} /home/franklin/chocolate_duke3D/build-aux/missing makeinfo
+MKDIR_P = /usr/bin/mkdir -p
+OBJEXT = o
+PACKAGE = chocolate-duke3d
+PACKAGE_BUGREPORT = https://github.com/fabiensanglard/chocolate_duke3D/issues
+PACKAGE_NAME = Chocolate Duke3D
+PACKAGE_STRING = Chocolate Duke3D 1.0
+PACKAGE_TARNAME = chocolate-duke3d
+PACKAGE_URL =
+PACKAGE_VERSION = 1.0
+PATH_SEPARATOR = :
+PKG_CONFIG = /usr/bin/pkg-config
+PKG_CONFIG_LIBDIR =
+PKG_CONFIG_PATH =
+RANLIB = ranlib
+SDL_CFLAGS = -D_GNU_SOURCE=1 -D_REENTRANT -I/usr/include/SDL
+SDL_LIBS = -lSDL -lpthread
+SDL_MIXER_CFLAGS = -D_GNU_SOURCE=1 -D_REENTRANT -I/usr/include/SDL
+SDL_MIXER_LIBS = -lSDL_mixer -lSDL -lpthread
+SET_MAKE =
+SHELL = /bin/sh
+STRIP =
+VERSION = 1.0
+WINDRES =
+abs_builddir = /home/franklin/chocolate_duke3D/Engine/src
+abs_srcdir = /home/franklin/chocolate_duke3D/Engine/src
+abs_top_builddir = /home/franklin/chocolate_duke3D
+abs_top_srcdir = /home/franklin/chocolate_duke3D
+ac_ct_CC = gcc
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = $${TAR-tar} chof - "$$tardir"
+am__untar = $${TAR-tar} xf -
+bindir = ${exec_prefix}/bin
+build_alias =
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host_alias =
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/franklin/chocolate_duke3D/build-aux/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = $(MKDIR_P)
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias =
+top_build_prefix = ../../
+top_builddir = ../..
+top_srcdir = ../..
+noinst_LIBRARIES = libEngine.a
+libEngine_a_SOURCES = cache.c display.c draw.c dummy_multi.c engine.c filesystem.c fixedPoint_math.c mmulti.c network.c tiles.c
+libEngine_a_CFLAGS = -I$(top_srcdir)/Game/src
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Engine/src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Engine/src/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libEngine.a: $(libEngine_a_OBJECTS) $(libEngine_a_DEPENDENCIES) $(EXTRA_libEngine_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libEngine.a
+ $(AM_V_AR)$(libEngine_a_AR) libEngine.a $(libEngine_a_OBJECTS) $(libEngine_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libEngine.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+include ./$(DEPDIR)/libEngine_a-cache.Po
+include ./$(DEPDIR)/libEngine_a-display.Po
+include ./$(DEPDIR)/libEngine_a-draw.Po
+include ./$(DEPDIR)/libEngine_a-dummy_multi.Po
+include ./$(DEPDIR)/libEngine_a-engine.Po
+include ./$(DEPDIR)/libEngine_a-filesystem.Po
+include ./$(DEPDIR)/libEngine_a-fixedPoint_math.Po
+include ./$(DEPDIR)/libEngine_a-mmulti.Po
+include ./$(DEPDIR)/libEngine_a-network.Po
+include ./$(DEPDIR)/libEngine_a-tiles.Po
+
+.c.o:
+ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# $(AM_V_CC)source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# $(AM_V_CC)source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+libEngine_a-cache.o: cache.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-cache.o -MD -MP -MF $(DEPDIR)/libEngine_a-cache.Tpo -c -o libEngine_a-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-cache.Tpo $(DEPDIR)/libEngine_a-cache.Po
+# $(AM_V_CC)source='cache.c' object='libEngine_a-cache.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
+
+libEngine_a-cache.obj: cache.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-cache.obj -MD -MP -MF $(DEPDIR)/libEngine_a-cache.Tpo -c -o libEngine_a-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-cache.Tpo $(DEPDIR)/libEngine_a-cache.Po
+# $(AM_V_CC)source='cache.c' object='libEngine_a-cache.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
+
+libEngine_a-display.o: display.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-display.o -MD -MP -MF $(DEPDIR)/libEngine_a-display.Tpo -c -o libEngine_a-display.o `test -f 'display.c' || echo '$(srcdir)/'`display.c
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-display.Tpo $(DEPDIR)/libEngine_a-display.Po
+# $(AM_V_CC)source='display.c' object='libEngine_a-display.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-display.o `test -f 'display.c' || echo '$(srcdir)/'`display.c
+
+libEngine_a-display.obj: display.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-display.obj -MD -MP -MF $(DEPDIR)/libEngine_a-display.Tpo -c -o libEngine_a-display.obj `if test -f 'display.c'; then $(CYGPATH_W) 'display.c'; else $(CYGPATH_W) '$(srcdir)/display.c'; fi`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-display.Tpo $(DEPDIR)/libEngine_a-display.Po
+# $(AM_V_CC)source='display.c' object='libEngine_a-display.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-display.obj `if test -f 'display.c'; then $(CYGPATH_W) 'display.c'; else $(CYGPATH_W) '$(srcdir)/display.c'; fi`
+
+libEngine_a-draw.o: draw.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-draw.o -MD -MP -MF $(DEPDIR)/libEngine_a-draw.Tpo -c -o libEngine_a-draw.o `test -f 'draw.c' || echo '$(srcdir)/'`draw.c
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-draw.Tpo $(DEPDIR)/libEngine_a-draw.Po
+# $(AM_V_CC)source='draw.c' object='libEngine_a-draw.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-draw.o `test -f 'draw.c' || echo '$(srcdir)/'`draw.c
+
+libEngine_a-draw.obj: draw.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-draw.obj -MD -MP -MF $(DEPDIR)/libEngine_a-draw.Tpo -c -o libEngine_a-draw.obj `if test -f 'draw.c'; then $(CYGPATH_W) 'draw.c'; else $(CYGPATH_W) '$(srcdir)/draw.c'; fi`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-draw.Tpo $(DEPDIR)/libEngine_a-draw.Po
+# $(AM_V_CC)source='draw.c' object='libEngine_a-draw.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-draw.obj `if test -f 'draw.c'; then $(CYGPATH_W) 'draw.c'; else $(CYGPATH_W) '$(srcdir)/draw.c'; fi`
+
+libEngine_a-dummy_multi.o: dummy_multi.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-dummy_multi.o -MD -MP -MF $(DEPDIR)/libEngine_a-dummy_multi.Tpo -c -o libEngine_a-dummy_multi.o `test -f 'dummy_multi.c' || echo '$(srcdir)/'`dummy_multi.c
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-dummy_multi.Tpo $(DEPDIR)/libEngine_a-dummy_multi.Po
+# $(AM_V_CC)source='dummy_multi.c' object='libEngine_a-dummy_multi.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-dummy_multi.o `test -f 'dummy_multi.c' || echo '$(srcdir)/'`dummy_multi.c
+
+libEngine_a-dummy_multi.obj: dummy_multi.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-dummy_multi.obj -MD -MP -MF $(DEPDIR)/libEngine_a-dummy_multi.Tpo -c -o libEngine_a-dummy_multi.obj `if test -f 'dummy_multi.c'; then $(CYGPATH_W) 'dummy_multi.c'; else $(CYGPATH_W) '$(srcdir)/dummy_multi.c'; fi`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-dummy_multi.Tpo $(DEPDIR)/libEngine_a-dummy_multi.Po
+# $(AM_V_CC)source='dummy_multi.c' object='libEngine_a-dummy_multi.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-dummy_multi.obj `if test -f 'dummy_multi.c'; then $(CYGPATH_W) 'dummy_multi.c'; else $(CYGPATH_W) '$(srcdir)/dummy_multi.c'; fi`
+
+libEngine_a-engine.o: engine.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-engine.o -MD -MP -MF $(DEPDIR)/libEngine_a-engine.Tpo -c -o libEngine_a-engine.o `test -f 'engine.c' || echo '$(srcdir)/'`engine.c
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-engine.Tpo $(DEPDIR)/libEngine_a-engine.Po
+# $(AM_V_CC)source='engine.c' object='libEngine_a-engine.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-engine.o `test -f 'engine.c' || echo '$(srcdir)/'`engine.c
+
+libEngine_a-engine.obj: engine.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-engine.obj -MD -MP -MF $(DEPDIR)/libEngine_a-engine.Tpo -c -o libEngine_a-engine.obj `if test -f 'engine.c'; then $(CYGPATH_W) 'engine.c'; else $(CYGPATH_W) '$(srcdir)/engine.c'; fi`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-engine.Tpo $(DEPDIR)/libEngine_a-engine.Po
+# $(AM_V_CC)source='engine.c' object='libEngine_a-engine.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-engine.obj `if test -f 'engine.c'; then $(CYGPATH_W) 'engine.c'; else $(CYGPATH_W) '$(srcdir)/engine.c'; fi`
+
+libEngine_a-filesystem.o: filesystem.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-filesystem.o -MD -MP -MF $(DEPDIR)/libEngine_a-filesystem.Tpo -c -o libEngine_a-filesystem.o `test -f 'filesystem.c' || echo '$(srcdir)/'`filesystem.c
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-filesystem.Tpo $(DEPDIR)/libEngine_a-filesystem.Po
+# $(AM_V_CC)source='filesystem.c' object='libEngine_a-filesystem.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-filesystem.o `test -f 'filesystem.c' || echo '$(srcdir)/'`filesystem.c
+
+libEngine_a-filesystem.obj: filesystem.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-filesystem.obj -MD -MP -MF $(DEPDIR)/libEngine_a-filesystem.Tpo -c -o libEngine_a-filesystem.obj `if test -f 'filesystem.c'; then $(CYGPATH_W) 'filesystem.c'; else $(CYGPATH_W) '$(srcdir)/filesystem.c'; fi`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-filesystem.Tpo $(DEPDIR)/libEngine_a-filesystem.Po
+# $(AM_V_CC)source='filesystem.c' object='libEngine_a-filesystem.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-filesystem.obj `if test -f 'filesystem.c'; then $(CYGPATH_W) 'filesystem.c'; else $(CYGPATH_W) '$(srcdir)/filesystem.c'; fi`
+
+libEngine_a-fixedPoint_math.o: fixedPoint_math.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-fixedPoint_math.o -MD -MP -MF $(DEPDIR)/libEngine_a-fixedPoint_math.Tpo -c -o libEngine_a-fixedPoint_math.o `test -f 'fixedPoint_math.c' || echo '$(srcdir)/'`fixedPoint_math.c
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-fixedPoint_math.Tpo $(DEPDIR)/libEngine_a-fixedPoint_math.Po
+# $(AM_V_CC)source='fixedPoint_math.c' object='libEngine_a-fixedPoint_math.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-fixedPoint_math.o `test -f 'fixedPoint_math.c' || echo '$(srcdir)/'`fixedPoint_math.c
+
+libEngine_a-fixedPoint_math.obj: fixedPoint_math.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-fixedPoint_math.obj -MD -MP -MF $(DEPDIR)/libEngine_a-fixedPoint_math.Tpo -c -o libEngine_a-fixedPoint_math.obj `if test -f 'fixedPoint_math.c'; then $(CYGPATH_W) 'fixedPoint_math.c'; else $(CYGPATH_W) '$(srcdir)/fixedPoint_math.c'; fi`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-fixedPoint_math.Tpo $(DEPDIR)/libEngine_a-fixedPoint_math.Po
+# $(AM_V_CC)source='fixedPoint_math.c' object='libEngine_a-fixedPoint_math.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-fixedPoint_math.obj `if test -f 'fixedPoint_math.c'; then $(CYGPATH_W) 'fixedPoint_math.c'; else $(CYGPATH_W) '$(srcdir)/fixedPoint_math.c'; fi`
+
+libEngine_a-mmulti.o: mmulti.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-mmulti.o -MD -MP -MF $(DEPDIR)/libEngine_a-mmulti.Tpo -c -o libEngine_a-mmulti.o `test -f 'mmulti.c' || echo '$(srcdir)/'`mmulti.c
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-mmulti.Tpo $(DEPDIR)/libEngine_a-mmulti.Po
+# $(AM_V_CC)source='mmulti.c' object='libEngine_a-mmulti.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-mmulti.o `test -f 'mmulti.c' || echo '$(srcdir)/'`mmulti.c
+
+libEngine_a-mmulti.obj: mmulti.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-mmulti.obj -MD -MP -MF $(DEPDIR)/libEngine_a-mmulti.Tpo -c -o libEngine_a-mmulti.obj `if test -f 'mmulti.c'; then $(CYGPATH_W) 'mmulti.c'; else $(CYGPATH_W) '$(srcdir)/mmulti.c'; fi`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-mmulti.Tpo $(DEPDIR)/libEngine_a-mmulti.Po
+# $(AM_V_CC)source='mmulti.c' object='libEngine_a-mmulti.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-mmulti.obj `if test -f 'mmulti.c'; then $(CYGPATH_W) 'mmulti.c'; else $(CYGPATH_W) '$(srcdir)/mmulti.c'; fi`
+
+libEngine_a-network.o: network.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-network.o -MD -MP -MF $(DEPDIR)/libEngine_a-network.Tpo -c -o libEngine_a-network.o `test -f 'network.c' || echo '$(srcdir)/'`network.c
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-network.Tpo $(DEPDIR)/libEngine_a-network.Po
+# $(AM_V_CC)source='network.c' object='libEngine_a-network.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-network.o `test -f 'network.c' || echo '$(srcdir)/'`network.c
+
+libEngine_a-network.obj: network.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-network.obj -MD -MP -MF $(DEPDIR)/libEngine_a-network.Tpo -c -o libEngine_a-network.obj `if test -f 'network.c'; then $(CYGPATH_W) 'network.c'; else $(CYGPATH_W) '$(srcdir)/network.c'; fi`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-network.Tpo $(DEPDIR)/libEngine_a-network.Po
+# $(AM_V_CC)source='network.c' object='libEngine_a-network.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-network.obj `if test -f 'network.c'; then $(CYGPATH_W) 'network.c'; else $(CYGPATH_W) '$(srcdir)/network.c'; fi`
+
+libEngine_a-tiles.o: tiles.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-tiles.o -MD -MP -MF $(DEPDIR)/libEngine_a-tiles.Tpo -c -o libEngine_a-tiles.o `test -f 'tiles.c' || echo '$(srcdir)/'`tiles.c
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-tiles.Tpo $(DEPDIR)/libEngine_a-tiles.Po
+# $(AM_V_CC)source='tiles.c' object='libEngine_a-tiles.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-tiles.o `test -f 'tiles.c' || echo '$(srcdir)/'`tiles.c
+
+libEngine_a-tiles.obj: tiles.c
+ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-tiles.obj -MD -MP -MF $(DEPDIR)/libEngine_a-tiles.Tpo -c -o libEngine_a-tiles.obj `if test -f 'tiles.c'; then $(CYGPATH_W) 'tiles.c'; else $(CYGPATH_W) '$(srcdir)/tiles.c'; fi`
+ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-tiles.Tpo $(DEPDIR)/libEngine_a-tiles.Po
+# $(AM_V_CC)source='tiles.c' object='libEngine_a-tiles.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(AM_V_CC_no)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-tiles.obj `if test -f 'tiles.c'; then $(CYGPATH_W) 'tiles.c'; else $(CYGPATH_W) '$(srcdir)/tiles.c'; fi`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/Makefile.am b/apps/plugins/sdl/progs/duke3d/Engine/src/Makefile.am
new file mode 100644
index 0000000000..74eff1286e
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/Makefile.am
@@ -0,0 +1,3 @@
+noinst_LIBRARIES = libEngine.a
+libEngine_a_SOURCES = cache.c display.c draw.c dummy_multi.c engine.c filesystem.c fixedPoint_math.c mmulti.c network.c tiles.c
+libEngine_a_CFLAGS = -I$(top_srcdir)/Game/src
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/Makefile.in b/apps/plugins/sdl/progs/duke3d/Engine/src/Makefile.in
new file mode 100644
index 0000000000..cf7465b165
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/Makefile.in
@@ -0,0 +1,693 @@
+# Makefile.in generated by automake 1.15.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = Engine/src
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+AR = ar
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+libEngine_a_AR = $(AR) $(ARFLAGS)
+libEngine_a_LIBADD =
+am_libEngine_a_OBJECTS = libEngine_a-cache.$(OBJEXT) \
+ libEngine_a-display.$(OBJEXT) libEngine_a-draw.$(OBJEXT) \
+ libEngine_a-dummy_multi.$(OBJEXT) libEngine_a-engine.$(OBJEXT) \
+ libEngine_a-filesystem.$(OBJEXT) \
+ libEngine_a-fixedPoint_math.$(OBJEXT) \
+ libEngine_a-mmulti.$(OBJEXT) libEngine_a-network.$(OBJEXT) \
+ libEngine_a-tiles.$(OBJEXT)
+libEngine_a_OBJECTS = $(am_libEngine_a_OBJECTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libEngine_a_SOURCES)
+DIST_SOURCES = $(libEngine_a_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in \
+ $(top_srcdir)/build-aux/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_LIBS = @SDL_LIBS@
+SDL_MIXER_CFLAGS = @SDL_MIXER_CFLAGS@
+SDL_MIXER_LIBS = @SDL_MIXER_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LIBRARIES = libEngine.a
+libEngine_a_SOURCES = cache.c display.c draw.c dummy_multi.c engine.c filesystem.c fixedPoint_math.c mmulti.c network.c tiles.c
+libEngine_a_CFLAGS = -I$(top_srcdir)/Game/src
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Engine/src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Engine/src/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+libEngine.a: $(libEngine_a_OBJECTS) $(libEngine_a_DEPENDENCIES) $(EXTRA_libEngine_a_DEPENDENCIES)
+ $(AM_V_at)-rm -f libEngine.a
+ $(AM_V_AR)$(libEngine_a_AR) libEngine.a $(libEngine_a_OBJECTS) $(libEngine_a_LIBADD)
+ $(AM_V_at)$(RANLIB) libEngine.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libEngine_a-cache.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libEngine_a-display.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libEngine_a-draw.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libEngine_a-dummy_multi.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libEngine_a-engine.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libEngine_a-filesystem.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libEngine_a-fixedPoint_math.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libEngine_a-mmulti.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libEngine_a-network.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libEngine_a-tiles.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+libEngine_a-cache.o: cache.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-cache.o -MD -MP -MF $(DEPDIR)/libEngine_a-cache.Tpo -c -o libEngine_a-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-cache.Tpo $(DEPDIR)/libEngine_a-cache.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='libEngine_a-cache.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
+
+libEngine_a-cache.obj: cache.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-cache.obj -MD -MP -MF $(DEPDIR)/libEngine_a-cache.Tpo -c -o libEngine_a-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-cache.Tpo $(DEPDIR)/libEngine_a-cache.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='libEngine_a-cache.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
+
+libEngine_a-display.o: display.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-display.o -MD -MP -MF $(DEPDIR)/libEngine_a-display.Tpo -c -o libEngine_a-display.o `test -f 'display.c' || echo '$(srcdir)/'`display.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-display.Tpo $(DEPDIR)/libEngine_a-display.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display.c' object='libEngine_a-display.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-display.o `test -f 'display.c' || echo '$(srcdir)/'`display.c
+
+libEngine_a-display.obj: display.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-display.obj -MD -MP -MF $(DEPDIR)/libEngine_a-display.Tpo -c -o libEngine_a-display.obj `if test -f 'display.c'; then $(CYGPATH_W) 'display.c'; else $(CYGPATH_W) '$(srcdir)/display.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-display.Tpo $(DEPDIR)/libEngine_a-display.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='display.c' object='libEngine_a-display.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-display.obj `if test -f 'display.c'; then $(CYGPATH_W) 'display.c'; else $(CYGPATH_W) '$(srcdir)/display.c'; fi`
+
+libEngine_a-draw.o: draw.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-draw.o -MD -MP -MF $(DEPDIR)/libEngine_a-draw.Tpo -c -o libEngine_a-draw.o `test -f 'draw.c' || echo '$(srcdir)/'`draw.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-draw.Tpo $(DEPDIR)/libEngine_a-draw.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='draw.c' object='libEngine_a-draw.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-draw.o `test -f 'draw.c' || echo '$(srcdir)/'`draw.c
+
+libEngine_a-draw.obj: draw.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-draw.obj -MD -MP -MF $(DEPDIR)/libEngine_a-draw.Tpo -c -o libEngine_a-draw.obj `if test -f 'draw.c'; then $(CYGPATH_W) 'draw.c'; else $(CYGPATH_W) '$(srcdir)/draw.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-draw.Tpo $(DEPDIR)/libEngine_a-draw.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='draw.c' object='libEngine_a-draw.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-draw.obj `if test -f 'draw.c'; then $(CYGPATH_W) 'draw.c'; else $(CYGPATH_W) '$(srcdir)/draw.c'; fi`
+
+libEngine_a-dummy_multi.o: dummy_multi.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-dummy_multi.o -MD -MP -MF $(DEPDIR)/libEngine_a-dummy_multi.Tpo -c -o libEngine_a-dummy_multi.o `test -f 'dummy_multi.c' || echo '$(srcdir)/'`dummy_multi.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-dummy_multi.Tpo $(DEPDIR)/libEngine_a-dummy_multi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dummy_multi.c' object='libEngine_a-dummy_multi.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-dummy_multi.o `test -f 'dummy_multi.c' || echo '$(srcdir)/'`dummy_multi.c
+
+libEngine_a-dummy_multi.obj: dummy_multi.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-dummy_multi.obj -MD -MP -MF $(DEPDIR)/libEngine_a-dummy_multi.Tpo -c -o libEngine_a-dummy_multi.obj `if test -f 'dummy_multi.c'; then $(CYGPATH_W) 'dummy_multi.c'; else $(CYGPATH_W) '$(srcdir)/dummy_multi.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-dummy_multi.Tpo $(DEPDIR)/libEngine_a-dummy_multi.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dummy_multi.c' object='libEngine_a-dummy_multi.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-dummy_multi.obj `if test -f 'dummy_multi.c'; then $(CYGPATH_W) 'dummy_multi.c'; else $(CYGPATH_W) '$(srcdir)/dummy_multi.c'; fi`
+
+libEngine_a-engine.o: engine.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-engine.o -MD -MP -MF $(DEPDIR)/libEngine_a-engine.Tpo -c -o libEngine_a-engine.o `test -f 'engine.c' || echo '$(srcdir)/'`engine.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-engine.Tpo $(DEPDIR)/libEngine_a-engine.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='engine.c' object='libEngine_a-engine.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-engine.o `test -f 'engine.c' || echo '$(srcdir)/'`engine.c
+
+libEngine_a-engine.obj: engine.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-engine.obj -MD -MP -MF $(DEPDIR)/libEngine_a-engine.Tpo -c -o libEngine_a-engine.obj `if test -f 'engine.c'; then $(CYGPATH_W) 'engine.c'; else $(CYGPATH_W) '$(srcdir)/engine.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-engine.Tpo $(DEPDIR)/libEngine_a-engine.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='engine.c' object='libEngine_a-engine.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-engine.obj `if test -f 'engine.c'; then $(CYGPATH_W) 'engine.c'; else $(CYGPATH_W) '$(srcdir)/engine.c'; fi`
+
+libEngine_a-filesystem.o: filesystem.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-filesystem.o -MD -MP -MF $(DEPDIR)/libEngine_a-filesystem.Tpo -c -o libEngine_a-filesystem.o `test -f 'filesystem.c' || echo '$(srcdir)/'`filesystem.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-filesystem.Tpo $(DEPDIR)/libEngine_a-filesystem.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='filesystem.c' object='libEngine_a-filesystem.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-filesystem.o `test -f 'filesystem.c' || echo '$(srcdir)/'`filesystem.c
+
+libEngine_a-filesystem.obj: filesystem.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-filesystem.obj -MD -MP -MF $(DEPDIR)/libEngine_a-filesystem.Tpo -c -o libEngine_a-filesystem.obj `if test -f 'filesystem.c'; then $(CYGPATH_W) 'filesystem.c'; else $(CYGPATH_W) '$(srcdir)/filesystem.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-filesystem.Tpo $(DEPDIR)/libEngine_a-filesystem.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='filesystem.c' object='libEngine_a-filesystem.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-filesystem.obj `if test -f 'filesystem.c'; then $(CYGPATH_W) 'filesystem.c'; else $(CYGPATH_W) '$(srcdir)/filesystem.c'; fi`
+
+libEngine_a-fixedPoint_math.o: fixedPoint_math.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-fixedPoint_math.o -MD -MP -MF $(DEPDIR)/libEngine_a-fixedPoint_math.Tpo -c -o libEngine_a-fixedPoint_math.o `test -f 'fixedPoint_math.c' || echo '$(srcdir)/'`fixedPoint_math.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-fixedPoint_math.Tpo $(DEPDIR)/libEngine_a-fixedPoint_math.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fixedPoint_math.c' object='libEngine_a-fixedPoint_math.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-fixedPoint_math.o `test -f 'fixedPoint_math.c' || echo '$(srcdir)/'`fixedPoint_math.c
+
+libEngine_a-fixedPoint_math.obj: fixedPoint_math.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-fixedPoint_math.obj -MD -MP -MF $(DEPDIR)/libEngine_a-fixedPoint_math.Tpo -c -o libEngine_a-fixedPoint_math.obj `if test -f 'fixedPoint_math.c'; then $(CYGPATH_W) 'fixedPoint_math.c'; else $(CYGPATH_W) '$(srcdir)/fixedPoint_math.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-fixedPoint_math.Tpo $(DEPDIR)/libEngine_a-fixedPoint_math.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fixedPoint_math.c' object='libEngine_a-fixedPoint_math.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-fixedPoint_math.obj `if test -f 'fixedPoint_math.c'; then $(CYGPATH_W) 'fixedPoint_math.c'; else $(CYGPATH_W) '$(srcdir)/fixedPoint_math.c'; fi`
+
+libEngine_a-mmulti.o: mmulti.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-mmulti.o -MD -MP -MF $(DEPDIR)/libEngine_a-mmulti.Tpo -c -o libEngine_a-mmulti.o `test -f 'mmulti.c' || echo '$(srcdir)/'`mmulti.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-mmulti.Tpo $(DEPDIR)/libEngine_a-mmulti.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmulti.c' object='libEngine_a-mmulti.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-mmulti.o `test -f 'mmulti.c' || echo '$(srcdir)/'`mmulti.c
+
+libEngine_a-mmulti.obj: mmulti.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-mmulti.obj -MD -MP -MF $(DEPDIR)/libEngine_a-mmulti.Tpo -c -o libEngine_a-mmulti.obj `if test -f 'mmulti.c'; then $(CYGPATH_W) 'mmulti.c'; else $(CYGPATH_W) '$(srcdir)/mmulti.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-mmulti.Tpo $(DEPDIR)/libEngine_a-mmulti.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmulti.c' object='libEngine_a-mmulti.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-mmulti.obj `if test -f 'mmulti.c'; then $(CYGPATH_W) 'mmulti.c'; else $(CYGPATH_W) '$(srcdir)/mmulti.c'; fi`
+
+libEngine_a-network.o: network.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-network.o -MD -MP -MF $(DEPDIR)/libEngine_a-network.Tpo -c -o libEngine_a-network.o `test -f 'network.c' || echo '$(srcdir)/'`network.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-network.Tpo $(DEPDIR)/libEngine_a-network.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='network.c' object='libEngine_a-network.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-network.o `test -f 'network.c' || echo '$(srcdir)/'`network.c
+
+libEngine_a-network.obj: network.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-network.obj -MD -MP -MF $(DEPDIR)/libEngine_a-network.Tpo -c -o libEngine_a-network.obj `if test -f 'network.c'; then $(CYGPATH_W) 'network.c'; else $(CYGPATH_W) '$(srcdir)/network.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-network.Tpo $(DEPDIR)/libEngine_a-network.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='network.c' object='libEngine_a-network.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-network.obj `if test -f 'network.c'; then $(CYGPATH_W) 'network.c'; else $(CYGPATH_W) '$(srcdir)/network.c'; fi`
+
+libEngine_a-tiles.o: tiles.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-tiles.o -MD -MP -MF $(DEPDIR)/libEngine_a-tiles.Tpo -c -o libEngine_a-tiles.o `test -f 'tiles.c' || echo '$(srcdir)/'`tiles.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-tiles.Tpo $(DEPDIR)/libEngine_a-tiles.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tiles.c' object='libEngine_a-tiles.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-tiles.o `test -f 'tiles.c' || echo '$(srcdir)/'`tiles.c
+
+libEngine_a-tiles.obj: tiles.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -MT libEngine_a-tiles.obj -MD -MP -MF $(DEPDIR)/libEngine_a-tiles.Tpo -c -o libEngine_a-tiles.obj `if test -f 'tiles.c'; then $(CYGPATH_W) 'tiles.c'; else $(CYGPATH_W) '$(srcdir)/tiles.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libEngine_a-tiles.Tpo $(DEPDIR)/libEngine_a-tiles.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tiles.c' object='libEngine_a-tiles.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libEngine_a_CFLAGS) $(CFLAGS) -c -o libEngine_a-tiles.obj `if test -f 'tiles.c'; then $(CYGPATH_W) 'tiles.c'; else $(CYGPATH_W) '$(srcdir)/tiles.c'; fi`
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/build.h b/apps/plugins/sdl/progs/duke3d/Engine/src/build.h
new file mode 100644
index 0000000000..f0389e54e2
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/build.h
@@ -0,0 +1,320 @@
+/*
+ * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * See the included license file "BUILDLIC.TXT" for license info.
+ * This file has been modified from Ken Silverman's original release
+ */
+
+#ifndef _INCLUDE_BUILD_H_
+#define _INCLUDE_BUILD_H_
+#ifdef _WIN32
+ #include "windows/inttypes.h"
+#else
+ #include <inttypes.h>
+#endif
+
+#define MAXSECTORS 1024
+#define MAXWALLS 8192
+#define MAXSPRITES 4096
+#define MAXTILES 9216
+
+#define MAXSTATUS 1024
+#define MAXPLAYERS 16
+#define MAXXDIM 1600
+#define MAXYDIM 1200
+#define MAXPALOOKUPS 256
+#define MAXPSKYTILES 256
+#define MAXSPRITESONSCREEN 1024
+
+#define CLIPMASK0 (((1L)<<16)+1L)
+#define CLIPMASK1 (((256L)<<16)+64L)
+
+
+ /*
+ * Make all variables in BUILD.H defined in the ENGINE,
+ * and externed in GAME
+ * (dear lord. --ryan.)
+ */
+#ifdef ENGINE
+ #define EXTERN
+#else
+ #define EXTERN extern
+#endif
+
+#pragma pack(1)
+
+/*
+ * ceilingstat/floorstat:
+ * bit 0: 1 = parallaxing, 0 = not "P"
+ * bit 1: 1 = groudraw, 0 = not
+ * bit 2: 1 = swap x&y, 0 = not "F"
+ * bit 3: 1 = double smooshiness "E"
+ * bit 4: 1 = x-flip "F"
+ * bit 5: 1 = y-flip "F"
+ * bit 6: 1 = Align texture to first wall of sector "R"
+ * bits 7-8: "T"
+ * 00 = normal floors
+ * 01 = masked floors
+ * 10 = transluscent masked floors
+ * 11 = reverse transluscent masked floors
+ * bits 9-15: reserved
+ */
+
+ /* 40 bytes */
+typedef struct
+{
+ short wallptr, wallnum;
+ int32_t ceilingz, floorz;
+ short ceilingstat, floorstat;
+ short ceilingpicnum, ceilingheinum;
+ int8_t ceilingshade;
+ uint8_t ceilingpal, ceilingxpanning, ceilingypanning;
+ short floorpicnum, floorheinum;
+ int8_t floorshade;
+ uint8_t floorpal, floorxpanning, floorypanning;
+ uint8_t visibility, filler;
+ short lotag, hitag, extra;
+} sectortype;
+
+/*
+ * cstat:
+ * bit 0: 1 = Blocking wall (use with clipmove, getzrange) "B"
+ * bit 1: 1 = bottoms of invisible walls swapped, 0 = not "2"
+ * bit 2: 1 = align picture on bottom (for doors), 0 = top "O"
+ * bit 3: 1 = x-flipped, 0 = normal "F"
+ * bit 4: 1 = masking wall, 0 = not "M"
+ * bit 5: 1 = 1-way wall, 0 = not "1"
+ * bit 6: 1 = Blocking wall (use with hitscan / cliptype 1) "H"
+ * bit 7: 1 = Transluscence, 0 = not "T"
+ * bit 8: 1 = y-flipped, 0 = normal "F"
+ * bit 9: 1 = Transluscence reversing, 0 = normal "T"
+ * bits 10-15: reserved
+ */
+
+ /* 32 bytes */
+typedef struct
+{
+ int32_t x, y;
+ short point2, nextwall, nextsector, cstat;
+ short picnum, overpicnum;
+ int8_t shade;
+ uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
+ short lotag, hitag, extra;
+} walltype;
+
+
+/*
+ * cstat:
+ * bit 0: 1 = Blocking sprite (use with clipmove, getzrange) "B"
+ * bit 1: 1 = transluscence, 0 = normal "T"
+ * bit 2: 1 = x-flipped, 0 = normal "F"
+ * bit 3: 1 = y-flipped, 0 = normal "F"
+ * bits 5-4: 00 = FACE sprite (default) "R"
+ * 01 = WALL sprite (like masked walls)
+ * 10 = FLOOR sprite (parallel to ceilings&floors)
+ * bit 6: 1 = 1-sided sprite, 0 = normal "1"
+ * bit 7: 1 = Real centered centering, 0 = foot center "C"
+ * bit 8: 1 = Blocking sprite (use with hitscan / cliptype 1) "H"
+ * bit 9: 1 = Transluscence reversing, 0 = normal "T"
+ * bits 10-14: reserved
+ * bit 15: 1 = Invisible sprite, 0 = not invisible
+ */
+
+ /* 44 bytes */
+typedef struct
+{
+ int32_t x, y, z;
+ short cstat, picnum;
+ int8_t shade;
+ uint8_t pal, clipdist, filler;
+ uint8_t xrepeat, yrepeat;
+ int8_t xoffset, yoffset;
+ short sectnum, statnum;
+ short ang, owner, xvel, yvel, zvel;
+ short lotag, hitag, extra;
+} spritetype;
+
+#pragma pack()
+
+EXTERN sectortype sector[MAXSECTORS];
+EXTERN walltype wall[MAXWALLS];
+EXTERN spritetype sprite[MAXSPRITES];
+
+EXTERN uint16_t mapCRC;
+
+EXTERN int32_t spritesortcnt;
+EXTERN spritetype tsprite[MAXSPRITESONSCREEN];
+
+EXTERN uint8_t vidoption;
+EXTERN int32_t xdim, ydim, numpages;
+
+// Fast way to retrive the start of a column in the framebuffer, given a screenspace X coordinate.
+EXTERN int32_t ylookup[MAXYDIM+1];
+
+EXTERN int32_t yxaspect, viewingrange;
+
+EXTERN int32_t validmodecnt;
+EXTERN short validmode[256];
+EXTERN int32_t validmodexdim[256], validmodeydim[256];
+
+EXTERN short numsectors, numwalls;
+EXTERN volatile int32_t totalclock;
+EXTERN int32_t numframes, randomseed;
+EXTERN short sintable[2048];
+EXTERN uint8_t palette[768];
+EXTERN short numpalookups;
+EXTERN uint8_t *palookup[MAXPALOOKUPS];
+EXTERN uint8_t parallaxtype, showinvisibility;
+EXTERN int32_t parallaxyoffs, parallaxyscale;
+EXTERN int32_t visibility, parallaxvisibility;
+
+EXTERN int32_t windowx1, windowy1, windowx2, windowy2;
+EXTERN short startumost[MAXXDIM], startdmost[MAXXDIM];
+
+EXTERN short pskyoff[MAXPSKYTILES], pskybits;
+
+EXTERN short headspritesect[MAXSECTORS+1], headspritestat[MAXSTATUS+1];
+EXTERN short prevspritesect[MAXSPRITES], prevspritestat[MAXSPRITES];
+EXTERN short nextspritesect[MAXSPRITES], nextspritestat[MAXSPRITES];
+
+
+
+ /*
+ * These variables are for auto-mapping with the draw2dscreen function.
+ * When you load a new board, these bits are all set to 0 - since
+ * you haven't mapped out anything yet. Note that these arrays are
+ * bit-mapped.
+ * If you want draw2dscreen() to show sprite #54 then you say:
+ * spritenum = 54;
+ * show2dsprite[spritenum>>3] |= (1<<(spritenum&7));
+ * And if you want draw2dscreen() to not show sprite #54 then you say:
+ * spritenum = 54;
+ * show2dsprite[spritenum>>3] &= ~(1<<(spritenum&7));
+ * Automapping defaults to 0 (do nothing). If you set automapping to 1,
+ * then in 3D mode, the walls and sprites that you see will show up the
+ * next time you flip to 2D mode.
+ */
+EXTERN uint8_t show2dsector[(MAXSECTORS+7)>>3];
+EXTERN uint8_t show2dwall[(MAXWALLS+7)>>3];
+EXTERN uint8_t show2dsprite[(MAXSPRITES+7)>>3];
+EXTERN uint8_t automapping;
+
+
+
+//This is the bit vector that marks visited sector during portal flooding. Size is hence (MAXSECTORS / 8)
+EXTERN uint8_t visitedSectors[(MAXSECTORS+7)>>3];
+
+/*************************************************************************
+POSITION VARIABLES:
+
+ POSX is your x - position ranging from 0 to 65535
+ POSY is your y - position ranging from 0 to 65535
+ (the length of a side of the grid in EDITBORD would be 1024)
+ POSZ is your z - position (height) ranging from 0 to 65535, 0 highest.
+ ANG is your angle ranging from 0 to 2047. Instead of 360 degrees, or
+ 2 * PI radians, I use 2048 different angles, so 90 degrees would
+ be 512 in my system.
+
+SPRITE VARIABLES:
+
+ EXTERN short headspritesect[MAXSECTORS+1], headspritestat[MAXSTATUS+1];
+ EXTERN short prevspritesect[MAXSPRITES], prevspritestat[MAXSPRITES];
+ EXTERN short nextspritesect[MAXSPRITES], nextspritestat[MAXSPRITES];
+
+ Example: if the linked lists look like the following:
+ 旼컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴커
+ Sector lists: Status lists:
+ 쳐컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴캑
+ Sector0: 4, 5, 8 Status0: 2, 0, 8
+ Sector1: 16, 2, 0, 7 Status1: 4, 5, 16, 7, 3, 9
+ Sector2: 3, 9
+ 읕컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴컴켸
+ Notice that each number listed above is shown exactly once on both the
+ left and right side. This is because any sprite that exists must
+ be in some sector, and must have some kind of status that you define.
+
+
+Coding example #1:
+ To go through all the sprites in sector 1, the code can look like this:
+
+ sectnum = 1;
+ i = headspritesect[sectnum];
+ while (i != -1)
+ {
+ nexti = nextspritesect[i];
+
+ //your code goes here
+ //ex: printf("Sprite %d is in sector %d\n",i,sectnum);
+
+ i = nexti;
+ }
+
+Coding example #2:
+ To go through all sprites with status = 1, the code can look like this:
+
+ statnum = 1; //status 1
+ i = headspritestat[statnum];
+ while (i != -1)
+ {
+ nexti = nextspritestat[i];
+
+ //your code goes here
+ //ex: printf("Sprite %d has a status of 1 (active)\n",i,statnum);
+
+ i = nexti;
+ }
+
+ insertsprite(short sectnum, short statnum);
+ deletesprite(short spritenum);
+ changespritesect(short spritenum, short newsectnum);
+ changespritestat(short spritenum, short newstatnum);
+
+TILE VARIABLES:
+ NUMTILES - the number of tiles found TILES.DAT.
+ TILESIZX[MAXTILES] - simply the x-dimension of the tile number.
+ TILESIZY[MAXTILES] - simply the y-dimension of the tile number.
+ WALOFF[MAXTILES] - the actual 32-bit offset pointing to the top-left
+ corner of the tile.
+ PICANM[MAXTILES] - flags for animating the tile.
+
+TIMING VARIABLES:
+ TOTALCLOCK - When the engine is initialized, TOTALCLOCK is set to zero.
+ From then on, it is incremented 120 times a second by 1. That
+ means that the number of seconds elapsed is totalclock / 120.
+ NUMFRAMES - The number of times the draw3dscreen function was called
+ since the engine was initialized. This helps to determine frame
+ rate. (Frame rate = numframes * 120 / totalclock.)
+
+OTHER VARIABLES:
+
+ STARTUMOST[320] is an array of the highest y-coordinates on each column
+ that my engine is allowed to write to. You need to set it only
+ once.
+ STARTDMOST[320] is an array of the lowest y-coordinates on each column
+ that my engine is allowed to write to. You need to set it only
+ once.
+ SINTABLE[2048] is a sin table with 2048 angles rather than the
+ normal 360 angles for higher precision. Also since SINTABLE is in
+ all integers, the range is multiplied by 16383, so instead of the
+ normal -1<sin(x)<1, the range of sintable is -16383<sintable[]<16383
+ If you use this sintable, you can possibly speed up your code as
+ well as save space in memory. If you plan to use sintable, 2
+ identities you may want to keep in mind are:
+ sintable[ang&2047] = sin(ang * (3.141592/1024)) * 16383
+ sintable[(ang+512)&2047] = cos(ang * (3.141592/1024)) * 16383
+ NUMSECTORS - the total number of existing sectors. Modified every time
+ you call the loadboard function.
+***************************************************************************/
+
+#define PORTSIG "Port by Ryan C. Gordon, Andrew Henderson, Dan Olson, Fabien Sanglard and a cast of thousands."
+
+//Global.c
+void Error (int errorType, char *error, ...);
+int FindDistance2D(int ix, int iy);
+
+#endif /* defined _INCLUDE_BUILD_H_ */
+
+/* end of build.h ... */
+
+
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/cache.c b/apps/plugins/sdl/progs/duke3d/Engine/src/cache.c
new file mode 100644
index 0000000000..2ac3bfe6d0
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/cache.c
@@ -0,0 +1,225 @@
+/*
+ * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * See the included license file "BUILDLIC.TXT" for license info.
+ * This file has been modified from Ken Silverman's original release
+ */
+
+#include "platform.h"
+#include "display.h"
+
+#include "fixedPoint_math.h"
+#include "cache.h"
+#include "build.h"
+
+#include "../../Game/src/cvar_defs.h"
+
+#include "../../Game/src/types.h"
+
+/*
+ * This module keeps track of a standard linear cacheing system.
+ * To use this module, here's all you need to do:
+ *
+ * Step 1: Allocate a nice BIG buffer, like from 1MB-4MB and
+ * Call initcache(int32_t cachestart, int32_t cachesize) where
+ *
+ * cachestart = (int32_t )(pointer to start of BIG buffer)
+ * cachesize = length of BIG buffer
+ *
+ * Step 2: Call allocache(int32_t *bufptr, int32_t bufsiz, uint8_t *lockptr)
+ * whenever you need to allocate a buffer, where:
+ *
+ * *bufptr = pointer to 4-byte pointer to buffer
+ * Confused? Using this method, cache2d can remove
+ * previously allocated things from the cache safely by
+ * setting the 4-byte pointer to 0.
+ * bufsiz = number of bytes to allocate
+ * *lockptr = pointer to locking uint8_t which tells whether
+ * the region can be removed or not. If *lockptr = 0 then
+ * the region is not locked else its locked.
+ *
+ * Step 3: If you need to remove everything from the cache, or every
+ * unlocked item from the cache, you can call uninitcache();
+ * Call uninitcache(0) to remove all unlocked items, or
+ * Call uninitcache(1) to remove everything.
+ * After calling uninitcache, it is still ok to call allocache
+ * without first calling initcache.
+ */
+
+#define MAXCACHEOBJECTS 9216
+
+static int32_t cachesize = 0;
+int32_t cachecount = 0;
+uint8_t zerochar = 0;
+uint8_t* cachestart = NULL;
+int32_t cacnum = 0, agecount = 0;
+
+typedef struct {
+ uint8_t** hand;
+ int32_t leng;
+ uint8_t *lock; }
+cactype;
+
+cactype cac[MAXCACHEOBJECTS];
+int32_t lockrecip[200];
+
+// TC game directory
+char game_dir[512] = "/.rockbox/duke3d";
+
+void initcache(uint8_t* dacachestart, int32_t dacachesize)
+{
+ int32_t i;
+
+ for(i=1;i<200;i++) lockrecip[i] = (1<<28)/(200-i);
+
+ cachestart = dacachestart;
+ cachesize = dacachesize;
+
+ cac[0].leng = cachesize;
+ cac[0].lock = &zerochar;
+ cacnum = 1;
+}
+
+void allocache (uint8_t** newhandle, int32_t newbytes, uint8_t *newlockptr)
+{
+ int32_t i, z, zz, bestz=0, daval, bestval, besto=0, o1, o2, sucklen, suckz;
+
+ newbytes = newbytes+15;
+
+ if ((uint32_t)newbytes > (uint32_t)cachesize)
+ {
+ printf("Cachesize: %d\n",cachesize);
+ printf("*Newhandle: 0x%x, Newbytes: %d, *Newlock: %d\n",(unsigned int)newhandle,newbytes,*newlockptr);
+ reportandexit("BUFFER TOO BIG TO FIT IN CACHE!\n");
+ }
+
+ if (*newlockptr == 0)
+ {
+ reportandexit("ALLOCACHE CALLED WITH LOCK OF 0!\n");
+ }
+
+ /* Find best place */
+ bestval = 0x7fffffff; o1 = cachesize;
+ for(z=cacnum-1;z>=0;z--)
+ {
+ o1 -= cac[z].leng;
+ o2 = o1+newbytes; if (o2 > cachesize) continue;
+
+ daval = 0;
+ for(i=o1,zz=z;i<o2;i+=cac[zz++].leng)
+ {
+ if (*cac[zz].lock == 0) continue;
+ if (*cac[zz].lock >= 200) { daval = 0x7fffffff; break; }
+ daval += (int32_t ) mulscale32(cac[zz].leng+65536,lockrecip[*cac[zz].lock]);
+ if (daval >= bestval) break;
+ }
+ if (daval < bestval)
+ {
+ bestval = daval; besto = o1; bestz = z;
+ if (bestval == 0) break;
+ }
+ }
+
+ /*printf("%ld %ld %ld\n",besto,newbytes,*newlockptr);*/
+
+ if (bestval == 0x7fffffff)
+ reportandexit("CACHE SPACE ALL LOCKED UP!\n");
+
+ /* Suck things out */
+ for(sucklen=-newbytes,suckz=bestz;sucklen<0;sucklen+=cac[suckz++].leng)
+ if (*cac[suckz].lock) *cac[suckz].hand = 0;
+
+ /* Remove all blocks except 1 */
+ suckz -= (bestz+1); cacnum -= suckz;
+ copybufbyte(&cac[bestz+suckz],&cac[bestz],(cacnum-bestz)*sizeof(cactype));
+ cac[bestz].hand = newhandle;
+ *newhandle = cachestart+besto;
+ cac[bestz].leng = newbytes;
+ cac[bestz].lock = newlockptr;
+ cachecount++;
+
+ /* Add new empty block if necessary */
+ if (sucklen <= 0) return;
+
+ bestz++;
+ if (bestz == cacnum)
+ {
+ cacnum++; if (cacnum > MAXCACHEOBJECTS) reportandexit("Too many objects in cache! (cacnum > MAXCACHEOBJECTS)\n");
+ cac[bestz].leng = sucklen;
+ cac[bestz].lock = &zerochar;
+ return;
+ }
+
+ if (*cac[bestz].lock == 0) { cac[bestz].leng += sucklen; return; }
+
+ cacnum++; if (cacnum > MAXCACHEOBJECTS) reportandexit("Too many objects in cache! (cacnum > MAXCACHEOBJECTS)\n");
+ for(z=cacnum-1;z>bestz;z--) cac[z] = cac[z-1];
+ cac[bestz].leng = sucklen;
+ cac[bestz].lock = &zerochar;
+}
+
+void suckcache (int32_t *suckptr)
+{
+ int32_t i;
+
+ /* Can't exit early, because invalid pointer might be same even though lock = 0 */
+ for(i=0;i<cacnum;i++)
+ if ((int32_t )(*cac[i].hand) == (int32_t )suckptr)
+ {
+ if (*cac[i].lock) *cac[i].hand = 0;
+ cac[i].lock = &zerochar;
+ cac[i].hand = 0;
+
+ /* Combine empty blocks */
+ if ((i > 0) && (*cac[i-1].lock == 0))
+ {
+ cac[i-1].leng += cac[i].leng;
+ cacnum--; copybuf(&cac[i+1],&cac[i],(cacnum-i)*sizeof(cactype));
+ }
+ else if ((i < cacnum-1) && (*cac[i+1].lock == 0))
+ {
+ cac[i+1].leng += cac[i].leng;
+ cacnum--; copybuf(&cac[i+1],&cac[i],(cacnum-i)*sizeof(cactype));
+ }
+ }
+}
+
+void agecache(void)
+{
+ int32_t cnt;
+ uint8_t ch;
+
+ if (agecount >= cacnum) agecount = cacnum-1;
+ assert(agecount >= 0);
+
+ for(cnt=(cacnum>>4);cnt>=0;cnt--)
+ {
+ ch = (*cac[agecount].lock);
+ if (((ch-2)&255) < 198)
+ (*cac[agecount].lock) = (uint8_t ) (ch-1);
+
+ agecount--; if (agecount < 0) agecount = cacnum-1;
+ }
+}
+
+void reportandexit(char *errormessage)
+{
+ int32_t i, j;
+
+ setvmode(0x3);
+ j = 0;
+ for(i=0;i<cacnum;i++)
+ {
+ printf("%d- ",i);
+ printf("ptr: 0x%x, ",(int8_t)*cac[i].hand);
+ printf("leng: %d, ",cac[i].leng);
+ printf("lock: %d\n",*cac[i].lock);
+ j += cac[i].leng;
+ }
+ printf("Cachesize = %d\n",cachesize);
+ printf("Cacnum = %d\n",cacnum);
+ printf("Cache length sum = %d\n",j);
+ printf("ERROR: %s",errormessage);
+ Error(EXIT_FAILURE, "");
+}
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/cache.h b/apps/plugins/sdl/progs/duke3d/Engine/src/cache.h
new file mode 100644
index 0000000000..b4754379ab
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/cache.h
@@ -0,0 +1,34 @@
+/*
+ * Cache1d declarations.
+ *
+ * Written by Ryan C. Gordon. (icculus@clutteredmind.org)
+ *
+ * Please do NOT harrass Ken Silverman about any code modifications
+ * (including this file) to BUILD.
+ */
+
+/*
+ * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * See the included license file "BUILDLIC.TXT" for license info.
+ * This file has been modified from Ken Silverman's original release
+ */
+
+#ifndef _INCLUDE_CACHE1D_H_
+#define _INCLUDE_CACHE1D_H_
+
+void initcache(uint8_t* dacachestart, int32_t dacachesize);
+void allocache (uint8_t* *newhandle, int32_t newbytes, uint8_t *newlockptr);
+void suckcache (int32_t *suckptr);
+void agecache(void);
+
+
+void reportandexit(char *errormessage);
+
+extern char game_dir[];
+
+//Filesystem
+
+
+
+#endif \ No newline at end of file
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/display.c b/apps/plugins/sdl/progs/duke3d/Engine/src/display.c
new file mode 100644
index 0000000000..3883803bce
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/display.c
@@ -0,0 +1,1949 @@
+/*
+ * An SDL replacement for BUILD's VESA code.
+ *
+ * Written by Ryan C. Gordon. (icculus@clutteredmind.org)
+ *
+ * Please do NOT harrass Ken Silverman about any code modifications
+ * (including this file) to BUILD.
+ */
+
+/*
+ * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * See the included license file "BUILDLIC.TXT" for license info.
+ * This file IS NOT A PART OF Ken Silverman's original release
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include "platform.h"
+
+#include "lib/pluginlib_bmp.h"
+#include "SDL_config.h"
+
+#if (!defined PLATFORM_SUPPORTS_SDL)
+#error This platform apparently does not use SDL. Do not compile this.
+#endif
+
+
+#define BUILD_NOMOUSEGRAB "BUILD_NOMOUSEGRAB"
+#define BUILD_WINDOWED "BUILD_WINDOWED"
+#define BUILD_SDLDEBUG "BUILD_SDLDEBUG"
+#define BUILD_RENDERER "BUILD_RENDERER"
+#define BUILD_GLLIBRARY "BUILD_GLLIBRARY"
+#define BUILD_USERSCREENRES "BUILD_USERSCREENRES"
+#define BUILD_MAXSCREENRES "BUILD_MAXSCREENRES"
+#define BUILD_HALLOFMIRRORS "BUILD_HALLOFMIRRORS"
+#define BUILD_GLDUMP "BUILD_GLDUMP"
+#define BUILD_SDLJOYSTICK "BUILD_SDLJOYSTICK"
+
+#include "SDL.h"
+#include "build.h"
+#include "display.h"
+#include "fixedPoint_math.h"
+#include "engine.h"
+#include "network.h"
+
+#include "mmulti_unstable.h"
+#include "mmulti_stable.h"
+#include "network.h"
+#include "icon.h"
+
+// NATIVE TIMER FUNCTION DECLARATION
+/*
+ FCS: The timer section sadly uses Native high precision calls to implement timer functions.
+ QueryPerformanceFrequency and QueryPerformanceCounter
+ it seems SDL precision was not good enough (or rather using unaccurate OS functions) to replicate
+ a DOS timer.
+ */
+
+int TIMER_GetPlatformTicksInOneSecond(int64_t* t);
+void TIMER_GetPlatformTicks(int64_t* t);
+
+//END // NATIVE TIMER FUNCTION DECLARATION
+
+
+
+
+
+
+#if ((defined PLATFORM_WIN32))
+#include <windows.h>
+#endif
+
+#include "draw.h"
+#include "cache.h"
+
+
+/*
+ * !!! remove the surface_end checks, for speed's sake. They are a
+ * !!! needed safety right now. --ryan.
+ */
+
+
+#define DEFAULT_MAXRESWIDTH 1600
+#define DEFAULT_MAXRESHEIGHT 1200
+
+
+#define UNLOCK_SURFACE_AND_RETURN if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); return;
+
+
+ /* !!! move these elsewhere? */
+int32_t xres, yres, bytesperline, imageSize, maxpages;
+uint8_t* frameplace;
+
+//The frambuffer address
+uint8_t* frameoffset;
+uint8_t *screen, vesachecked;
+int32_t buffermode, origbuffermode, linearmode;
+uint8_t permanentupdate = 0, vgacompatible;
+
+SDL_Surface *surface = NULL; /* This isn't static so that we can use it elsewhere AH */
+
+static uint32_t sdl_flags = SDL_HWPALETTE;
+static int32_t mouse_relative_x = 0;
+static int32_t mouse_relative_y = 0;
+static short mouse_buttons = 0;
+static unsigned int lastkey = 0;
+/* so we can make use of setcolor16()... - DDOI */
+static uint8_t drawpixel_color=0;
+
+static uint32_t scancodes[SDLK_LAST];
+
+static int32_t last_render_ticks = 0;
+int32_t total_render_time = 1;
+int32_t total_rendered_frames = 0;
+
+static char *titleNameLong = NULL;
+static char *titleNameShort = NULL;
+
+void restore256_palette (void);
+void set16color_palette (void);
+
+
+
+static void __append_sdl_surface_flag(SDL_Surface *_surface, char *str,
+ size_t strsize, Uint32 flag,
+ const char *flagstr)
+{
+ if (_surface->flags & flag)
+ {
+ if ( (strlen(str) + strlen(flagstr)) >= (strsize - 1) )
+ strcpy(str + (strsize - 5), " ...");
+ else
+ strcat(str, flagstr);
+ } /* if */
+}
+
+
+#define append_sdl_surface_flag(a, b, c, fl) __append_sdl_surface_flag(a, b, c, fl, " " #fl)
+#define print_tf_state(str, val) printf("%s: {%s}\n", str, (val) ? "true" : "false" )
+
+static void output_surface_info(SDL_Surface *_surface)
+{
+ const SDL_VideoInfo *info;
+ char f[256];
+
+
+ if (_surface == NULL)
+ {
+ printf("-WARNING- You've got a NULL screen surface!");
+ }
+ else
+ {
+ f[0] = '\0';
+ printf("screen surface is (%dx%dx%dbpp).\n",_surface->w, _surface->h, _surface->format->BitsPerPixel);
+
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SWSURFACE);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWSURFACE);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_ASYNCBLIT);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_ANYFORMAT);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWPALETTE);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_DOUBLEBUF);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_FULLSCREEN);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_OPENGL);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_OPENGLBLIT);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RESIZABLE);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_NOFRAME);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWACCEL);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SRCCOLORKEY);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RLEACCELOK);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RLEACCEL);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SRCALPHA);
+ append_sdl_surface_flag(_surface, f, sizeof (f), SDL_PREALLOC);
+
+ if (f[0] == '\0')
+ strcpy(f, " (none)");
+
+ printf("New vidmode flags:%s.\n", f);
+
+ info = SDL_GetVideoInfo();
+ assert(info != NULL);
+/*
+ print_tf_state("hardware surface available", info->hw_available);
+ print_tf_state("window manager available", info->wm_available);
+ print_tf_state("accelerated hardware->hardware blits", info->blit_hw);
+ print_tf_state("accelerated hardware->hardware colorkey blits", info->blit_hw_CC);
+ print_tf_state("accelerated hardware->hardware alpha blits", info->blit_hw_A);
+ print_tf_state("accelerated software->hardware blits", info->blit_sw);
+ print_tf_state("accelerated software->hardware colorkey blits", info->blit_sw_CC);
+ print_tf_state("accelerated software->hardware alpha blits", info->blit_sw_A);
+ print_tf_state("accelerated color fills", info->blit_fill);
+
+ printf("video memory: (%d),\n", info->video_mem);
+ */
+ }
+}
+
+
+static void output_driver_info(void)
+{
+ char buffer[256];
+
+ if (SDL_VideoDriverName(buffer, sizeof (buffer)) == NULL){
+ printf("-WARNING- SDL_VideoDriverName() returned NULL!");
+ } /* if */
+ else
+ {
+ printf("Using SDL video driver \"%s\".", buffer);
+ } /* else */
+} /* output_driver_info */
+
+
+void* get_framebuffer(void){
+ return((Uint8 *) surface->pixels);
+}
+
+
+
+/*
+ * !!! This is almost an entire copy of the original setgamemode().
+ * !!! Figure out what is needed for just 2D mode, and separate that
+ * !!! out. Then, place the original setgamemode() back into engine.c,
+ * !!! and remove our simple implementation (and this function.)
+ * !!! Just be sure to keep the non-DOS things, like the window's
+ * !!! titlebar caption. --ryan.
+ */
+static uint8_t screenalloctype = 255;
+static void init_new_res_vars(int32_t davidoption)
+{
+ int i = 0;
+ int j = 0;
+
+ setupmouse();
+
+ SDL_WM_SetCaption(titleNameLong, titleNameShort);
+
+ xdim = xres = surface->w;
+ ydim = yres = surface->h;
+
+ printf("init_new_res_vars %d %d\n",xdim,ydim);
+
+ bytesperline = surface->w;
+ vesachecked = 1;
+ vgacompatible = 1;
+ linearmode = 1;
+ qsetmode = surface->h;
+ activepage = visualpage = 0;
+
+
+ frameoffset = frameplace = (uint8_t*)surface->pixels;
+
+ if (screen != NULL)
+ {
+ if (screenalloctype == 0) kkfree((void *)screen);
+ if (screenalloctype == 1) suckcache((int32_t *)screen);
+ screen = NULL;
+ } /* if */
+
+
+ switch(vidoption)
+ {
+ case 1:i = xdim*ydim; break;
+ case 2: xdim = 320; ydim = 200; i = xdim*ydim; break;
+
+ default: assert(0);
+ }
+ j = ydim*4*sizeof(int32_t); /* Leave room for horizlookup&horizlookup2 */
+
+ if(horizlookup)
+ free(horizlookup);
+
+ if(horizlookup2)
+ free(horizlookup2);
+
+ horizlookup = (int32_t*)malloc(j);
+ horizlookup2 = (int32_t*)malloc(j);
+
+ j = 0;
+
+ //Build lookup table (X screespace -> frambuffer offset.
+ for(i = 0; i <= ydim; i++)
+ {
+ ylookup[i] = j;
+ j += bytesperline;
+ }
+
+ horizycent = ((ydim*4)>>1);
+
+ /* Force drawrooms to call dosetaspect & recalculate stuff */
+ oxyaspect = oxdimen = oviewingrange = -1;
+
+ //Let the Assembly module how many pixels to skip when drawing a column
+ setBytesPerLine(bytesperline);
+
+
+ setview(0L,0L,xdim-1,ydim-1);
+
+ setbrightness(curbrightness, palette);
+
+ if (searchx < 0) {
+ searchx = halfxdimen;
+ searchy = (ydimen>>1);
+ }
+
+}
+
+
+
+static void go_to_new_vid_mode(int davidoption, int w, int h)
+{
+ getvalidvesamodes();
+ SDL_ClearError();
+ // don't do SDL_SetVideoMode if SDL_WM_SetIcon not called. See sdl doc for SDL_WM_SetIcon
+ surface = SDL_SetVideoMode(w, h, 8, sdl_flags);
+ if (surface == NULL)
+ {
+ Error(EXIT_FAILURE, "BUILDSDL: Failed to set %dx%d video mode!\n"
+ "BUILDSDL: SDL_Error() says [%s].\n",
+ w, h, SDL_GetError());
+ } /* if */
+
+ output_surface_info(surface);
+ init_new_res_vars(davidoption); // dont be confused between vidoption (global) and davidoption
+}
+
+static __inline int sdl_mouse_button_filter(SDL_MouseButtonEvent const *event)
+{
+ /*
+ * What bits BUILD expects:
+ * 0 left button pressed if 1
+ * 1 right button pressed if 1
+ * 2 middle button pressed if 1
+ *
+ * (That is, this is what Int 33h (AX=0x05) returns...)
+ *
+ * additionally bits 3&4 are set for the mouse wheel
+ */
+ Uint8 button = event->button;
+ if (button >= sizeof (mouse_buttons) * 8)
+ return(0);
+
+ if (button == SDL_BUTTON_RIGHT)
+ button = SDL_BUTTON_MIDDLE;
+ else if (button == SDL_BUTTON_MIDDLE)
+ button = SDL_BUTTON_RIGHT;
+
+ if (((const SDL_MouseButtonEvent*)event)->state)
+ mouse_buttons |= 1<<(button-1);
+ else if (button != 4 && button != 5)
+ mouse_buttons ^= 1<<(button-1);
+#if 0
+ Uint8 bmask = SDL_GetMouseState(NULL, NULL);
+ mouse_buttons = 0;
+ if (bmask & SDL_BUTTON_LMASK) mouse_buttons |= 1;
+ if (bmask & SDL_BUTTON_RMASK) mouse_buttons |= 2;
+ if (bmask & SDL_BUTTON_MMASK) mouse_buttons |= 4;
+#endif
+
+ return(0);
+} /* sdl_mouse_up_filter */
+
+
+static int sdl_mouse_motion_filter(SDL_Event const *event)
+{
+ if (surface == NULL)
+ return(0);
+
+ if (event->type == SDL_JOYBALLMOTION)
+ {
+ mouse_relative_x = event->jball.xrel/100;
+ mouse_relative_y = event->jball.yrel/100;
+ }
+ else
+ {
+ if (SDL_WM_GrabInput(SDL_GRAB_QUERY)==SDL_GRAB_ON)
+ {
+ mouse_relative_x += event->motion.xrel;
+ mouse_relative_y += event->motion.yrel;
+ //printf("sdl_mouse_motion_filter: mrx=%d, mry=%d, mx=%d, my=%d\n",
+ // mouse_relative_x, mouse_relative_y, event->motion.xrel, event->motion.yrel);
+
+ // mouse_relative_* is already reset in
+ // readmousexy(). It must not be
+ // reset here because calling this function does not mean
+ // we always handle the mouse.
+ // FIX_00001: Mouse speed is uneven and slower in windowed mode vs fullscreen mode.
+ }
+ else
+ mouse_relative_x = mouse_relative_y = 0;
+ }
+
+ return(0);
+} /* sdl_mouse_motion_filter */
+
+
+ /*
+ * The windib driver can't alert us to the keypad enter key, which
+ * Ken's code depends on heavily. It sends it as the same key as the
+ * regular return key. These users will have to hit SHIFT-ENTER,
+ * which we check for explicitly, and give the engine a keypad enter
+ * enter event.
+ */
+static __inline int handle_keypad_enter_hack(const SDL_Event *event)
+{
+ static int kp_enter_hack = 0;
+ int retval = 0;
+
+ if (event->key.keysym.sym == SDLK_RETURN)
+ {
+ if (event->key.state == SDL_PRESSED)
+ {
+ if (event->key.keysym.mod & KMOD_SHIFT)
+ {
+ kp_enter_hack = 1;
+ lastkey = scancodes[SDLK_KP_ENTER];
+ retval = 1;
+ } /* if */
+ } /* if */
+
+ else /* key released */
+ {
+ if (kp_enter_hack)
+ {
+ kp_enter_hack = 0;
+ lastkey = scancodes[SDLK_KP_ENTER];
+ retval = 1;
+ } /* if */
+ } /* if */
+ } /* if */
+
+ return(retval);
+} /* handle_keypad_enter_hack */
+
+void fullscreen_toggle_and_change_driver(void)
+{
+
+// FIX_00002: New Toggle Windowed/FullScreen system now simpler and will
+// dynamically change for Windib or Directx driver. Windowed/Fullscreen
+// toggle also made available from menu.
+// Replace attempt_fullscreen_toggle(SDL_Surface **surface, Uint32 *flags)
+
+ int32_t x,y;
+ x = surface->w;
+ y = surface->h;
+
+ BFullScreen =!BFullScreen;
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+ _platform_init(0, NULL, "Duke Nukem 3D", "Duke3D");
+ _setgamemode(ScreenMode,x,y);
+ //vscrn();
+
+ return;
+}
+
+static int sdl_key_filter(const SDL_Event *event)
+{
+ int extended;
+
+ if ( (event->key.keysym.sym == SDLK_m) &&
+ (event->key.state == SDL_PRESSED) &&
+ (event->key.keysym.mod & KMOD_CTRL) )
+ {
+
+
+ // FIX_00005: Mouse pointer can be toggled on/off (see mouse menu or use CTRL-M)
+ // This is usefull to move the duke window when playing in window mode.
+
+ if (SDL_WM_GrabInput(SDL_GRAB_QUERY)==SDL_GRAB_ON)
+ {
+ SDL_WM_GrabInput(SDL_GRAB_OFF);
+ SDL_ShowCursor(1);
+ }
+ else
+ {
+ SDL_WM_GrabInput(SDL_GRAB_ON);
+ SDL_ShowCursor(0);
+ }
+
+ return(0);
+ } /* if */
+
+ else if ( ( (event->key.keysym.sym == SDLK_RETURN) ||
+ (event->key.keysym.sym == SDLK_KP_ENTER) ) &&
+ (event->key.state == SDL_PRESSED) &&
+ (event->key.keysym.mod & KMOD_ALT) )
+ { fullscreen_toggle_and_change_driver();
+
+ // hack to discard the ALT key...
+ lastkey=scancodes[SDLK_RALT]>>8; // extended
+ keyhandler();
+ lastkey=(scancodes[SDLK_RALT]&0xff)+0x80; // Simulating Key up
+ keyhandler();
+ lastkey=(scancodes[SDLK_LALT]&0xff)+0x80; // Simulating Key up (not extended)
+ keyhandler();
+ SDL_SetModState(KMOD_NONE); // SDL doesnt see we are releasing the ALT-ENTER keys
+
+ return(0);
+ }
+
+ if (!handle_keypad_enter_hack(event))
+ lastkey = scancodes[event->key.keysym.sym];
+
+// printf("key.keysym.sym=%d\n", event->key.keysym.sym);
+
+ if (lastkey == 0x0000) /* No DOS equivalent defined. */
+ return(0);
+
+ extended = ((lastkey & 0xFF00) >> 8);
+ if (extended != 0)
+ {
+ lastkey = extended;
+ keyhandler();
+ lastkey = (scancodes[event->key.keysym.sym] & 0xFF);
+ } /* if */
+
+ if (event->key.state == SDL_RELEASED)
+ lastkey += 128; /* +128 signifies that the key is released in DOS. */
+
+ keyhandler();
+ return(0);
+} /* sdl_key_filter */
+
+
+static int root_sdl_event_filter(const SDL_Event *event)
+{
+ switch (event->type)
+ {
+ case SDL_KEYUP:
+ // FIX_00003: Pause mode is now fully responsive - (Thx to Jonathon Fowler tips)
+ if(event->key.keysym.sym == SDLK_PAUSE)
+ break;
+ case SDL_KEYDOWN:
+ return(sdl_key_filter(event));
+ case SDL_JOYBUTTONDOWN:
+ case SDL_JOYBUTTONUP:
+ {
+ //Do Nothing
+
+ //printf("Joybutton UP/DOWN\n");
+ //return(sdl_joystick_button_filter((const SDL_MouseButtonEvent*)event));
+ return 0;
+ }
+ case SDL_JOYBALLMOTION:
+ case SDL_MOUSEMOTION:
+ return(sdl_mouse_motion_filter(event));
+ case SDL_MOUSEBUTTONUP:
+ case SDL_MOUSEBUTTONDOWN:
+ return(sdl_mouse_button_filter((const SDL_MouseButtonEvent*)event));
+ case SDL_QUIT:
+ /* !!! rcg TEMP */
+ Error(EXIT_SUCCESS, "Exit through SDL\n");
+ default:
+ //printf("This event is not handled: %d\n",event->type);
+ break;
+ } /* switch */
+
+ return(1);
+} /* root_sdl_event_filter */
+
+
+static void handle_events(void)
+{
+ SDL_Event event;
+
+ while(SDL_PollEvent(&event))
+ root_sdl_event_filter(&event);
+} /* handle_events */
+
+
+/* bleh...public version... */
+void _handle_events(void)
+{
+ handle_events();
+} /* _handle_events */
+
+
+static SDL_Joystick *joystick = NULL;
+void _joystick_init(void)
+{
+ const char *envr = getenv(BUILD_SDLJOYSTICK);
+ int favored = 0;
+ int numsticks;
+ int i;
+
+ if (joystick != NULL)
+ {
+ printf("Joystick appears to be already initialized.\n");
+ printf("...deinitializing for stick redetection...\n");
+ _joystick_deinit();
+ } /* if */
+
+ if ((envr != NULL) && (strcmp(envr, "none") == 0))
+ {
+ printf("Skipping joystick detection/initialization at user request\n");
+ return;
+ } /* if */
+
+ printf("Initializing SDL joystick subsystem...");
+ printf(" (export environment variable BUILD_SDLJOYSTICK=none to skip)\n");
+
+ if (SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_NOPARACHUTE) != 0)
+ {
+ printf("SDL_Init(SDL_INIT_JOYSTICK) failed: [%s].\n", SDL_GetError());
+ return;
+ } /* if */
+
+ numsticks = SDL_NumJoysticks();
+ printf("SDL sees %d joystick%s.\n", numsticks, numsticks == 1 ? "" : "s");
+ if (numsticks == 0)
+ return;
+
+ for (i = 0; i < numsticks; i++)
+ {
+ const char *stickname = SDL_JoystickName(i);
+ if ((envr != NULL) && (strcmp(envr, stickname) == 0))
+ favored = i;
+
+ printf("Stick #%d: [%s]\n", i, stickname);
+ } /* for */
+
+ printf("Using Stick #%d.", favored);
+ if ((envr == NULL) && (numsticks > 1))
+ printf("Set BUILD_SDLJOYSTICK to one of the above names to change.\n");
+
+ joystick = SDL_JoystickOpen(favored);
+ if (joystick == NULL)
+ {
+ printf("Joystick #%d failed to init: %s\n", favored, SDL_GetError());
+ return;
+ } /* if */
+
+ printf("Joystick initialized. %d axes, %d buttons, %d hats, %d balls.\n",
+ SDL_JoystickNumAxes(joystick), SDL_JoystickNumButtons(joystick),
+ SDL_JoystickNumHats(joystick), SDL_JoystickNumBalls(joystick));
+
+ SDL_JoystickEventState(SDL_QUERY);
+} /* _joystick_init */
+
+
+void _joystick_deinit(void)
+{
+ if (joystick != NULL)
+ {
+ printf("Closing joystick device...\n");
+ SDL_JoystickClose(joystick);
+ printf("Joystick device closed. Deinitializing SDL subsystem...\n");
+ SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+ printf("SDL joystick subsystem deinitialized.\n");
+ joystick = NULL;
+ } /* if */
+} /* _joystick_deinit */
+
+
+int _joystick_update(void)
+{
+ if (joystick == NULL)
+ return(0);
+
+ SDL_JoystickUpdate();
+ return(1);
+} /* _joystick_update */
+
+
+int _joystick_axis(int axis)
+{
+ if (joystick == NULL)
+ {
+ return(0);
+ }
+
+ return(SDL_JoystickGetAxis(joystick, axis));
+} /* _joystick_axis */
+
+int _joystick_hat(int hat)
+{
+ if (joystick == NULL)
+ {
+ return(-1);
+ }
+
+ return(SDL_JoystickGetHat(joystick, hat));
+} /* _joystick_axis */
+
+int _joystick_button(int button)
+{
+ if (joystick == NULL)
+ return(0);
+
+ return(SDL_JoystickGetButton(joystick, button) != 0);
+} /* _joystick_button */
+
+
+uint8_t _readlastkeyhit(void)
+{
+ return(lastkey);
+} /* _readlastkeyhit */
+
+
+
+#if (!defined __DATE__)
+#define __DATE__ "a long, int32_t time ago"
+#endif
+
+static void output_sdl_versions(void)
+{
+ const SDL_version *linked_ver = SDL_Linked_Version();
+ SDL_version compiled_ver;
+
+ SDL_VERSION(&compiled_ver);
+
+ printf("SDL display driver for the BUILD engine initializing.\n");
+ printf(" sdl_driver.c by Ryan C. Gordon (icculus@clutteredmind.org).\n");
+ printf("Compiled %s against SDL version %d.%d.%d ...\n", __DATE__,
+ compiled_ver.major, compiled_ver.minor, compiled_ver.patch);
+ printf("Linked SDL version is %d.%d.%d ...\n",
+ linked_ver->major, linked_ver->minor, linked_ver->patch);
+} /* output_sdl_versions */
+
+
+/* lousy -ansi flag. :) */
+static char *string_dupe(const char *str)
+{
+ char *retval = malloc(strlen(str) + 1);
+ if (retval != NULL)
+ strcpy(retval, str);
+ return(retval);
+} /* string_dupe */
+
+
+
+
+
+
+
+void _platform_init(int argc, char **argv, const char *title, const char *iconName)
+{
+ int i;
+ int64_t timeElapsed;
+ char dummyString[4096];
+
+ // FIX_00061: "ERROR: Two players have the same random ID" too frequent cuz of internet windows times
+ TIMER_GetPlatformTicks(&timeElapsed);
+ srand(timeElapsed&0xFFFFFFFF);
+
+ Setup_UnstableNetworking();
+
+ // Look through the command line args
+ for(i = 0; i < argc; i++)
+ {
+ if(argv[i][0] == '-' )
+ {
+ if(strcmpi(argv[i], "-netmode_stable") == 0)
+ {
+ //fullscreen = 1;
+ //TODO:
+//TODO ( "[Todo: handle -netmode <int>]" )
+ Setup_StableNetworking();
+
+ }
+ }
+ }
+
+
+
+#ifdef __APPLE__
+ SDL_putenv("SDL_VIDEODRIVER=Quartz");
+#endif
+
+
+ if (SDL_Init(SDL_INIT_VIDEO) == -1){
+ Error(EXIT_FAILURE, "BUILDSDL: SDL_Init() failed!\nBUILDSDL: SDL_GetError() says \"%s\".\n", SDL_GetError());
+ }
+
+
+ // Set up the correct renderer
+ // Becarfull setenv can't reach dll in VC++
+ // A way to proceed is to integrate the SDL libs
+ // in the exe instead.
+
+ // FIX_00004: SDL.dll and SDL_Mixer.dll are now integrated within the exe
+ // (this also makes the Windib/Directx driver switching easier with SDL)
+
+ // This requires to recompile the whole sdl and sdl mixer with the lib
+ // switch instead of the default dll switch.
+
+ putenv("SDL_VIDEO_CENTERED=1");
+
+ if (title == NULL)
+ title = "BUILD";
+
+ if (iconName == NULL)
+ iconName = "BUILD";
+
+ titleNameLong = string_dupe(title);
+ titleNameShort = string_dupe(iconName);
+
+ sdl_flags = BFullScreen ? SDL_FULLSCREEN : 0;
+
+ sdl_flags |= SDL_HWPALETTE;
+
+
+ memset(scancodes, '\0', sizeof (scancodes));
+ scancodes[SDLK_ESCAPE] = 0x01;
+ scancodes[SDLK_1] = 0x02;
+ scancodes[SDLK_2] = 0x03;
+ scancodes[SDLK_3] = 0x04;
+ scancodes[SDLK_4] = 0x05;
+ scancodes[SDLK_5] = 0x06;
+ scancodes[SDLK_6] = 0x07;
+ scancodes[SDLK_7] = 0x08;
+ scancodes[SDLK_8] = 0x09;
+ scancodes[SDLK_9] = 0x0A;
+ scancodes[SDLK_0] = 0x0B;
+ scancodes[SDLK_MINUS] = 0x0C; /* was 0x4A */
+ scancodes[SDLK_EQUALS] = 0x0D; /* was 0x4E */
+ scancodes[SDLK_BACKSPACE] = 0x0E;
+ scancodes[SDLK_TAB] = 0x0F;
+ scancodes[SDLK_q] = 0x10;
+ scancodes[SDLK_w] = 0x11;
+ scancodes[SDLK_e] = 0x12;
+ scancodes[SDLK_r] = 0x13;
+ scancodes[SDLK_t] = 0x14;
+ scancodes[SDLK_y] = 0x15;
+ scancodes[SDLK_u] = 0x16;
+ scancodes[SDLK_i] = 0x17;
+ scancodes[SDLK_o] = 0x18;
+ scancodes[SDLK_p] = 0x19;
+ scancodes[SDLK_LEFTBRACKET] = 0x1A;
+ scancodes[SDLK_RIGHTBRACKET] = 0x1B;
+ scancodes[SDLK_RETURN] = 0x1C;
+ scancodes[SDLK_LCTRL] = 0x1D;
+ scancodes[SDLK_a] = 0x1E;
+ scancodes[SDLK_s] = 0x1F;
+ scancodes[SDLK_d] = 0x20;
+ scancodes[SDLK_f] = 0x21;
+ scancodes[SDLK_g] = 0x22;
+ scancodes[SDLK_h] = 0x23;
+ scancodes[SDLK_j] = 0x24;
+ scancodes[SDLK_k] = 0x25;
+ scancodes[SDLK_l] = 0x26;
+ scancodes[SDLK_SEMICOLON] = 0x27;
+ scancodes[SDLK_QUOTE] = 0x28;
+ scancodes[SDLK_BACKQUOTE] = 0x29;
+ scancodes[SDLK_LSHIFT] = 0x2A;
+ scancodes[SDLK_BACKSLASH] = 0x2B;
+ scancodes[SDLK_z] = 0x2C;
+ scancodes[SDLK_x] = 0x2D;
+ scancodes[SDLK_c] = 0x2E;
+ scancodes[SDLK_v] = 0x2F;
+ scancodes[SDLK_b] = 0x30;
+ scancodes[SDLK_n] = 0x31;
+ scancodes[SDLK_m] = 0x32;
+ scancodes[SDLK_COMMA] = 0x33;
+ scancodes[SDLK_PERIOD] = 0x34;
+ scancodes[SDLK_SLASH] = 0x35;
+ scancodes[SDLK_RSHIFT] = 0x36;
+ scancodes[SDLK_KP_MULTIPLY] = 0x37;
+ scancodes[SDLK_LALT] = 0x38;
+ scancodes[SDLK_SPACE] = 0x39;
+ scancodes[SDLK_CAPSLOCK] = 0x3A;
+ scancodes[SDLK_F1] = 0x3B;
+ scancodes[SDLK_F2] = 0x3C;
+ scancodes[SDLK_F3] = 0x3D;
+ scancodes[SDLK_F4] = 0x3E;
+ scancodes[SDLK_F5] = 0x3F;
+ scancodes[SDLK_F6] = 0x40;
+ scancodes[SDLK_F7] = 0x41;
+ scancodes[SDLK_F8] = 0x42;
+ scancodes[SDLK_F9] = 0x43;
+ scancodes[SDLK_F10] = 0x44;
+ scancodes[SDLK_NUMLOCK] = 0x45;
+ scancodes[SDLK_SCROLLOCK] = 0x46;
+ scancodes[SDLK_KP7] = 0x47;
+ scancodes[SDLK_KP8] = 0x48;
+ scancodes[SDLK_KP9] = 0x49;
+ scancodes[SDLK_KP_MINUS] = 0x4A;
+ scancodes[SDLK_KP4] = 0x4B;
+ scancodes[SDLK_KP5] = 0x4C;
+ scancodes[SDLK_KP6] = 0x4D;
+ scancodes[SDLK_KP_PLUS] = 0x4E;
+ scancodes[SDLK_KP1] = 0x4F;
+ scancodes[SDLK_KP2] = 0x50;
+ scancodes[SDLK_KP3] = 0x51;
+ scancodes[SDLK_KP0] = 0x52;
+ scancodes[SDLK_KP_PERIOD] = 0x53;
+ scancodes[SDLK_F11] = 0x57;
+ scancodes[SDLK_F12] = 0x58;
+ scancodes[SDLK_PAUSE] = 0x59; /* SBF - technically incorrect */
+
+ scancodes[SDLK_KP_ENTER] = 0xE01C;
+ scancodes[SDLK_RCTRL] = 0xE01D;
+ scancodes[SDLK_KP_DIVIDE] = 0xE035;
+ scancodes[SDLK_PRINT] = 0xE037; /* SBF - technically incorrect */
+ scancodes[SDLK_SYSREQ] = 0xE037; /* SBF - for windows... */
+ scancodes[SDLK_RALT] = 0xE038;
+ scancodes[SDLK_HOME] = 0xE047;
+ scancodes[SDLK_UP] = 0xE048;
+ scancodes[SDLK_PAGEUP] = 0xE049;
+ scancodes[SDLK_LEFT] = 0xE04B;
+ scancodes[SDLK_RIGHT] = 0xE04D;
+ scancodes[SDLK_END] = 0xE04F;
+ scancodes[SDLK_DOWN] = 0xE050;
+ scancodes[SDLK_PAGEDOWN] = 0xE051;
+ scancodes[SDLK_INSERT] = 0xE052;
+ scancodes[SDLK_DELETE] = 0xE053;
+
+
+
+ output_sdl_versions();
+ output_driver_info();
+
+
+ printf("Video Driver: '%s'.\n", SDL_VideoDriverName(dummyString, 20));
+
+}
+
+// Capture BMP of the current frame
+int screencapture(char *filename, uint8_t inverseit)
+{
+// FIX_00006: better naming system for screenshots + message when pic is taken.
+// Use ./screenshots folder. Screenshot code rerwritten. Faster and
+// makes smaller files. Doesn't freeze or lag the game anymore.
+
+ SDL_SaveBMP(surface, filename);
+ return 0;
+} /* screencapture */
+
+
+void setvmode(int mode)
+{
+
+ if (mode == 0x3) /* text mode. */
+ {
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+ return;
+ } else
+ printf("setvmode(0x%x) is unsupported in SDL driver.\n", mode);
+
+}
+
+int32_t _setgamemode(uint8_t davidoption, int32_t daxdim, int32_t daydim)
+{
+ int validated, i;
+ SDL_Surface *image;
+ Uint32 colorkey;
+
+ // don't override higher-res app icon on OS X
+#ifndef PLATFORM_MACOSX
+ // Install icon
+ image = SDL_LoadBMP_RW(SDL_RWFromMem(iconBMP, iconBMP_size), 1);
+ colorkey = 0; // index in this image to be transparent
+ SDL_SetColorKey(image, SDL_SRCCOLORKEY, colorkey);
+ SDL_WM_SetIcon(image,NULL);
+#endif
+
+ if (daxdim > MAXXDIM || daydim > MAXYDIM)
+ {
+ printf("Resolution %dx%d is too high. Changed to %dx%d\n", daxdim, daydim, MAXXDIM,MAXYDIM);
+ daxdim = MAXXDIM;
+ daydim = MAXYDIM;
+ }
+
+ getvalidvesamodes();
+
+ validated = 0;
+ for(i=0; i<validmodecnt; i++){
+ if(validmodexdim[i] == daxdim && validmodeydim[i] == daydim)
+ validated = 1;
+ }
+
+ if(!validated){
+ printf("Resolution %dx%d unsupported. Changed to 640x480\n", daxdim, daydim);
+ daxdim = LCD_WIDTH;
+ daydim = LCD_HEIGHT;
+ }
+
+ go_to_new_vid_mode((int) davidoption, daxdim, daydim);
+
+ qsetmode = 200;
+ last_render_ticks = getticks();
+
+ return(0);
+} /* setgamemode */
+
+
+static int get_dimensions_from_str(const char *str, int32_t *_w, int32_t *_h)
+{
+ char *xptr = NULL;
+ char *ptr = NULL;
+ int32_t w = -1;
+ int32_t h = -1;
+
+ if (str == NULL)
+ return(0);
+
+ xptr = strchr(str, 'x');
+ if (xptr == NULL)
+ return(0);
+
+ w = strtol(str, &ptr, 10);
+ if (ptr != xptr)
+ return(0);
+
+ xptr++;
+ h = strtol(xptr, &ptr, 10);
+ if ( (*xptr == '\0') || (*ptr != '\0') )
+ return(0);
+
+ if ((w <= 1) || (h <= 1))
+ return(0);
+
+ if (_w != NULL)
+ *_w = w;
+
+ if (_h != NULL)
+ *_h = h;
+
+ return(1);
+} /* get_dimensions_from_str */
+
+
+static __inline void get_max_screen_res(int32_t *max_w, int32_t *max_h)
+{
+ int32_t w = DEFAULT_MAXRESWIDTH;
+ int32_t h = DEFAULT_MAXRESHEIGHT;
+ const char *envr = getenv(BUILD_MAXSCREENRES);
+
+ if (envr != NULL)
+ {
+ if (!get_dimensions_from_str(envr, &w, &h))
+ {
+ printf("User's resolution ceiling [%s] is bogus!\n", envr);
+ w = DEFAULT_MAXRESWIDTH;
+ h = DEFAULT_MAXRESHEIGHT;
+ } /* if */
+ } /* if */
+
+ if (max_w != NULL)
+ *max_w = w;
+
+ if (max_h != NULL)
+ *max_h = h;
+}
+
+
+static void add_vesa_mode(const char *typestr, int w, int h)
+{
+ //printf("Adding %s resolution (%dx%d).\n", typestr, w, h);
+ validmode[validmodecnt] = validmodecnt;
+ validmodexdim[validmodecnt] = w;
+ validmodeydim[validmodecnt] = h;
+ validmodecnt++;
+} /* add_vesa_mode */
+
+
+/* Let the user specify a specific mode via environment variable. */
+static __inline void add_user_defined_resolution(void)
+{
+ int32_t w;
+ int32_t h;
+ const char *envr = getenv(BUILD_USERSCREENRES);
+
+ /* rockbox hack */
+ add_vesa_mode("rockbox", LCD_WIDTH, LCD_HEIGHT);
+ add_vesa_mode("rockbox", LCD_HEIGHT, LCD_WIDTH);
+
+
+ if (envr == NULL)
+ return;
+
+ if (get_dimensions_from_str(envr, &w, &h))
+ add_vesa_mode("user defined", w, h);
+ else
+ printf("User defined resolution [%s] is bogus!\n", envr);
+} /* add_user_defined_resolution */
+
+
+static __inline SDL_Rect **get_physical_resolutions(void)
+{
+ const SDL_VideoInfo *vidInfo = SDL_GetVideoInfo();
+ SDL_Rect **modes = SDL_ListModes(vidInfo->vfmt, sdl_flags | SDL_FULLSCREEN);
+ if (modes == NULL)
+ {
+ sdl_flags &= ~SDL_FULLSCREEN;
+ modes = SDL_ListModes(vidInfo->vfmt, sdl_flags); /* try without fullscreen. */
+ if (modes == NULL)
+ modes = (SDL_Rect **) -1; /* fuck it. */
+ } /* if */
+
+ if (modes == (SDL_Rect **) -1)
+ printf("Couldn't get any physical resolutions.\n");
+ else
+ {
+ printf("Highest physical resolution is (%dx%d).\n",
+ modes[0]->w, modes[0]->h);
+ } /* else */
+
+ return(modes);
+} /* get_physical_resolutions */
+
+
+static void remove_vesa_mode(int index, const char *reason)
+{
+ int i;
+
+ assert(index < validmodecnt);
+ //printf("Removing resolution #%d, %dx%d [%s].\n",index, validmodexdim[index], validmodeydim[index], reason);
+
+ for (i = index; i < validmodecnt - 1; i++)
+ {
+ validmode[i] = validmode[i + 1];
+ validmodexdim[i] = validmodexdim[i + 1];
+ validmodeydim[i] = validmodeydim[i + 1];
+ } /* for */
+
+ validmodecnt--;
+} /* remove_vesa_mode */
+
+
+static __inline void cull_large_vesa_modes(void)
+{
+ int32_t max_w;
+ int32_t max_h;
+ int i;
+
+ get_max_screen_res(&max_w, &max_h);
+ printf("Setting resolution ceiling to (%dx%d).\n", max_w, max_h);
+
+ for (i = 0; i < validmodecnt; i++)
+ {
+ if ((validmodexdim[i] > max_w) || (validmodeydim[i] > max_h))
+ {
+ remove_vesa_mode(i, "above resolution ceiling");
+ i--; /* list shrinks. */
+ } /* if */
+ } /* for */
+} /* cull_large_vesa_modes */
+
+
+static __inline void cull_duplicate_vesa_modes(void)
+{
+ int i;
+ int j;
+
+ for (i = 0; i < validmodecnt; i++){
+ for (j = i + 1; j < validmodecnt; j++){
+ if ( (validmodexdim[i] == validmodexdim[j]) &&(validmodeydim[i] == validmodeydim[j]) ){
+ remove_vesa_mode(j, "duplicate");
+ j--; /* list shrinks. */
+ }
+ }
+ }
+}
+
+
+#define swap_macro(tmp, x, y) { tmp = x; x = y; y = tmp; }
+
+/* be sure to call cull_duplicate_vesa_modes() before calling this. */
+static __inline void sort_vesa_modelist(void)
+{
+ int i;
+ int sorted;
+ int32_t tmp;
+
+ do
+ {
+ sorted = 1;
+ for (i = 0; i < validmodecnt - 1; i++)
+ {
+ if ( (validmodexdim[i] >= validmodexdim[i+1]) &&
+ (validmodeydim[i] >= validmodeydim[i+1]) )
+ {
+ sorted = 0;
+ swap_macro(tmp, validmode[i], validmode[i+1]);
+ swap_macro(tmp, validmodexdim[i], validmodexdim[i+1]);
+ swap_macro(tmp, validmodeydim[i], validmodeydim[i+1]);
+ } /* if */
+ } /* for */
+ } while (!sorted);
+} /* sort_vesa_modelist */
+
+
+static __inline void cleanup_vesa_modelist(void)
+{
+ cull_large_vesa_modes();
+ cull_duplicate_vesa_modes();
+ sort_vesa_modelist();
+} /* cleanup_vesa_modelist */
+
+
+static __inline void output_vesa_modelist(void)
+{
+ char buffer[256];
+ char numbuf[20];
+ int i;
+
+ buffer[0] = '\0';
+
+ for (i = 0; i < validmodecnt; i++)
+ {
+ sprintf(numbuf, " (%dx%d)",(int32_t) validmodexdim[i], (int32_t) validmodeydim[i]);
+
+ if ( (strlen(buffer) + strlen(numbuf)) >= (sizeof (buffer) - 1) )
+ strcpy(buffer + (sizeof (buffer) - 5), " ...");
+ else
+ strcat(buffer, numbuf);
+ } /* for */
+
+ printf("Final sorted modelist:%s", buffer);
+}
+
+
+void getvalidvesamodes(void)
+{
+ static int already_checked = 0;
+ int i;
+ SDL_Rect **modes = NULL;
+ int stdres[][2] = {
+ {320, 200}, {640, 350}, {640, 480},
+ {800, 600}, {1024, 768}
+ };
+
+ if (already_checked)
+ return;
+
+ already_checked = 1;
+ validmodecnt = 0;
+ vidoption = 1; /* !!! tmp */
+
+ /* fill in the standard resolutions... */
+ for (i = 0; i < sizeof (stdres) / sizeof (stdres[0]); i++)
+ add_vesa_mode("standard", stdres[i][0], stdres[i][1]);
+
+ /* Anything the hardware can specifically do is added now... */
+ modes = get_physical_resolutions();
+ for (i = 0; (modes != (SDL_Rect **) -1) && (modes[i] != NULL); i++)
+ add_vesa_mode("physical", modes[i]->w, modes[i]->h);
+
+ /* Now add specific resolutions that the user wants... */
+ add_user_defined_resolution();
+
+ /* get rid of dupes and bogus resolutions... */
+ cleanup_vesa_modelist();
+
+ /* print it out for debugging purposes... */
+ output_vesa_modelist();
+}
+
+uint8_t lastPalette[768];
+void WriteTranslucToFile(void){
+
+ uint8_t buffer[65535*4];
+ uint8_t tga_header[18];
+ uint8_t* transPointer = transluc;
+ uint8_t* bufferPointer = buffer;
+ int i;
+ FILE* file;
+
+ for (i=0; i < 65535; i++) {
+
+ bufferPointer[0] = (lastPalette[(*transPointer)*3+0]) / 63.0 * 255;
+ bufferPointer[1] = (lastPalette[(*transPointer)*3+1]) / 63.0 * 255;
+ bufferPointer[2] = (lastPalette[(*transPointer)*3+2]) / 63.0 * 255;
+ bufferPointer[3] = 255;
+
+ printf("%d,",*transPointer);
+ if (i%255 ==0)
+ printf("\n");
+
+ transPointer +=1;
+ bufferPointer+=4;
+ }
+
+
+
+ file = fopen("/transluc.tga", "w");
+
+ memset(tga_header, 0, 18);
+ tga_header[2] = 2;
+ tga_header[12] = (256 & 0x00FF);
+ tga_header[13] = (256 & 0xFF00) / 256;
+ tga_header[14] = (256 & 0x00FF) ;
+ tga_header[15] =(256 & 0xFF00) / 256;
+ tga_header[16] = 32 ;
+
+ fwrite(&tga_header, 18, sizeof(uint8_t), file);
+ fwrite(buffer, 65535, 4, file);
+ fclose(file);
+}
+
+void WritePaletteToFile(uint8_t* palette,const char* filename,int width, int height){
+
+ uint8_t tga_header[18];
+ uint8_t* buffer;
+ uint8_t* palettePointer = palette;
+ uint8_t* bufferPointer ;
+ int i;
+
+ FILE* file = fopen(filename, "w");
+
+
+ memset(tga_header, 0, 18);
+ tga_header[2] = 2;
+ tga_header[12] = (width & 0x00FF);
+ tga_header[13] = (width & 0xFF00) / 256;
+ tga_header[14] = (height & 0x00FF) ;
+ tga_header[15] =(height & 0xFF00) / 256;
+ tga_header[16] = 32 ;
+
+ fwrite(&tga_header, 18, sizeof(uint8_t), file);
+
+ bufferPointer = buffer = malloc(width*height*4);
+
+ for (i = 0 ; i < width*height ; i++)
+ {
+ bufferPointer[0] = palettePointer[0] / 63.0 * 255;
+ bufferPointer[1] = palettePointer[1] / 63.0 * 255;
+ bufferPointer[2] = palettePointer[2] / 63.0 * 255;
+ bufferPointer[3] = 255;
+
+ bufferPointer += 4;
+ palettePointer+= 3;
+ }
+
+ fwrite(buffer, width*height, 4, file);
+ fclose(file);
+
+ free(buffer);
+}
+
+
+void WriteLastPaletteToFile(){
+ WritePaletteToFile(lastPalette,"lastPalette.tga",16,16);
+}
+
+int VBE_setPalette(uint8_t *palettebuffer)
+/*
+ * (From Ken's docs:)
+ * Set (num) palette palette entries starting at (start)
+ * palette entries are in a 4-byte format in this order:
+ * 0: Blue (0-63)
+ * 1: Green (0-63)
+ * 2: Red (0-63)
+ * 3: Reserved
+ *
+ * Naturally, the bytes are in the reverse order that SDL wants them...
+ * More importantly, SDL wants the color elements in a range from 0-255,
+ * so we do a conversion.
+ */
+{
+ SDL_Color fmt_swap[256];
+ SDL_Color *sdlp = fmt_swap;
+ uint8_t *p = palettebuffer;
+ int i;
+ //static updated=0;
+
+ //if (updated >=1 )
+ // return ;
+
+ //WritePaletteToFile(palettebuffer,"lastPalette.tga",16,16);
+ //updated++;
+
+
+ //CODE EXPLORATION
+ //Used only to write the last palette to file.
+ memcpy(lastPalette, palettebuffer, 768);
+
+ for (i = 0; i < 256; i++){
+ sdlp->b = (Uint8) ((((float) *p++) / 63.0) * 255.0);
+ sdlp->g = (Uint8) ((((float) *p++) / 63.0) * 255.0);
+ sdlp->r = (Uint8) ((((float) *p++) / 63.0) * 255.0);
+ sdlp->unused = *p++; /* This byte is unused in BUILD, too. */
+ sdlp++;
+ }
+
+ return(SDL_SetColors(surface, fmt_swap, 0, 256));
+}
+
+
+int VBE_getPalette(int32_t start, int32_t num, uint8_t *palettebuffer)
+{
+ SDL_Color *sdlp = surface->format->palette->colors + start;
+ uint8_t *p = palettebuffer + (start * 4);
+ int i;
+
+ for (i = 0; i < num; i++)
+ {
+ *p++ = (Uint8) ((((float) sdlp->b) / 255.0) * 63.0);
+ *p++ = (Uint8) ((((float) sdlp->g) / 255.0) * 63.0);
+ *p++ = (Uint8) ((((float) sdlp->r) / 255.0) * 63.0);
+ *p++ = sdlp->unused; /* This byte is unused in both SDL and BUILD. */
+ sdlp++;
+ }
+
+ return(1);
+}
+
+
+void _uninitengine(void)
+{
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+} /* _uninitengine */
+
+
+
+
+int setupmouse(void)
+{
+
+ SDL_Event event;
+
+ if (surface == NULL)
+ return(0);
+
+ SDL_WM_GrabInput(SDL_GRAB_ON);
+ SDL_ShowCursor(0);
+
+ mouse_relative_x = mouse_relative_y = 0;
+
+ /*
+ * this global usually gets set by BUILD, but it's a one-shot
+ * deal, and we may not have an SDL surface at that point. --ryan.
+ */
+ moustat = 1;
+
+ // FIX_00063: Duke's angle changing or incorrect when using toggle fullscreen/window mode
+ while(SDL_PollEvent(&event)); // Empying the various pending events (especially the mouse one)
+
+ //SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
+
+ return(1);
+} /* setupmouse */
+
+
+void readmousexy(short *x, short *y)
+{
+ if (x)
+ *x = mouse_relative_x << 2;
+ if (y)
+ *y = mouse_relative_y << 2;
+
+ mouse_relative_x = mouse_relative_y = 0;
+} /* readmousexy */
+
+
+void readmousebstatus(short *bstatus)
+{
+ if (bstatus)
+ *bstatus = mouse_buttons;
+
+ // special wheel treatment: make it like a button click
+ if(mouse_buttons&8)
+ mouse_buttons ^= 8;
+ if(mouse_buttons&16)
+ mouse_buttons ^= 16;
+
+} /* readmousebstatus */
+
+
+void _updateScreenRect(int32_t x, int32_t y, int32_t w, int32_t h)
+{
+ SDL_UpdateRect(surface, x, y, w, h);
+}
+
+//int counter= 0 ;
+//char bmpName[256];
+void _nextpage(void)
+
+{
+ Uint32 ticks;
+
+ _handle_events();
+
+
+ SDL_UpdateRect(surface, 0, 0, 0, 0);
+
+ //sprintf(bmpName,"%d.bmp",counter++);
+ //SDL_SaveBMP(surface,bmpName);
+
+
+ //if (CLEAR_FRAMEBUFFER)
+ // SDL_FillRect(surface,NULL,0);
+
+ ticks = getticks();
+ total_render_time = (ticks - last_render_ticks);
+ if (total_render_time > 1000){
+ total_rendered_frames = 0;
+ total_render_time = 1;
+ last_render_ticks = ticks;
+ }
+ total_rendered_frames++;
+}
+
+
+uint8_t readpixel(uint8_t * offset)
+{
+ return *offset;
+}
+
+void drawpixel(uint8_t * location, uint8_t pixel)
+{
+ *location = pixel;
+}
+
+/* Fix this up The Right Way (TM) - DDOI */
+void setcolor16(uint8_t col)
+{
+ drawpixel_color = col;
+}
+
+void drawpixel16(int32_t offset)
+{
+ drawpixel((uint8_t*)surface->pixels + offset, drawpixel_color);
+} /* drawpixel16 */
+
+
+void fillscreen16(int32_t offset, int32_t color, int32_t blocksize)
+{
+ Uint8 *surface_end;
+ Uint8 *wanted_end;
+ Uint8 *pixels;
+
+ if (SDL_MUSTLOCK(surface))
+ SDL_LockSurface(surface);
+
+ pixels = get_framebuffer();
+
+ /* Make this function pageoffset aware - DDOI */
+ if (!pageoffset) {
+ offset = offset << 3;
+ offset += 640*336;
+ }
+
+ surface_end = (pixels + (surface->w * surface->h)) - 1;
+ wanted_end = (pixels + offset) + blocksize;
+
+ if (offset < 0)
+ offset = 0;
+
+ if (wanted_end > surface_end)
+ blocksize = ((uint32_t) surface_end) - ((uint32_t) pixels + offset);
+
+ memset(pixels + offset, (int) color, blocksize);
+
+ if (SDL_MUSTLOCK(surface))
+ SDL_UnlockSurface(surface);
+
+ _nextpage();
+} /* fillscreen16 */
+
+
+/* Most of this line code is taken from Abrash's "Graphics Programming Blackbook".
+Remember, sharing code is A Good Thing. AH */
+static __inline void DrawHorizontalRun (uint8_t **ScreenPtr, int XAdvance, int RunLength, uint8_t Color)
+{
+ int i;
+ uint8_t *WorkingScreenPtr = *ScreenPtr;
+
+ for (i=0; i<RunLength; i++)
+ {
+ *WorkingScreenPtr = Color;
+ WorkingScreenPtr += XAdvance;
+ }
+ WorkingScreenPtr += surface->w;
+ *ScreenPtr = WorkingScreenPtr;
+}
+
+static __inline void DrawVerticalRun (uint8_t **ScreenPtr, int XAdvance, int RunLength, uint8_t Color)
+{
+ int i;
+ uint8_t *WorkingScreenPtr = *ScreenPtr;
+
+ for (i=0; i<RunLength; i++)
+ {
+ *WorkingScreenPtr = Color;
+ WorkingScreenPtr += surface->w;
+ }
+ WorkingScreenPtr += XAdvance;
+ *ScreenPtr = WorkingScreenPtr;
+}
+
+void drawline16(int32_t XStart, int32_t YStart, int32_t XEnd, int32_t YEnd, uint8_t Color)
+{
+ int Temp, AdjUp, AdjDown, ErrorTerm, XAdvance, XDelta, YDelta;
+ int WholeStep, InitialPixelCount, FinalPixelCount, i, RunLength;
+ uint8_t *ScreenPtr;
+ int32_t dx, dy;
+
+ if (SDL_MUSTLOCK(surface))
+ SDL_LockSurface(surface);
+
+ dx = XEnd-XStart;
+ dy = YEnd-YStart;
+
+ //Analyse the slope
+ if (dx >= 0)
+ {
+ if ((XStart > 639) || (XEnd < 0)) return;
+ if (XStart < 0) { if (dy) YStart += scale(0-XStart,dy,dx); XStart = 0; }
+ if (XEnd > 639) { if (dy) YEnd += scale(639-XEnd,dy,dx); XEnd = 639; }
+ }
+ else
+ {
+ if ((XEnd > 639) || (XStart < 0)) return;
+ if (XEnd < 0) { if (dy) YEnd += scale(0-XEnd,dy,dx); XEnd = 0; }
+ if (XStart > 639) { if (dy) YStart += scale(639-XStart,dy,dx); XStart = 639; }
+ }
+ if (dy >= 0)
+ {
+ if ((YStart >= ydim16) || (YEnd < 0)) return;
+ if (YStart < 0) { if (dx) XStart += scale(0-YStart,dx,dy); YStart = 0; }
+ if (YEnd >= ydim16) { if (dx) XEnd += scale(ydim16-1-YEnd,dx,dy); YEnd = ydim16-1; }
+ }
+ else
+ {
+ if ((YEnd >= ydim16) || (YStart < 0)) return;
+ if (YEnd < 0) { if (dx) XEnd += scale(0-YEnd,dx,dy); YEnd = 0; }
+ if (YStart >= ydim16) { if (dx) XStart += scale(ydim16-1-YStart,dx,dy); YStart = ydim16-1; }
+ }
+
+ /* Make sure the status bar border draws correctly - DDOI */
+ if (!pageoffset) { YStart += 336; YEnd += 336; }
+
+ /* We'll always draw top to bottom */
+ if (YStart > YEnd) {
+ Temp = YStart;
+ YStart = YEnd;
+ YEnd = Temp;
+ Temp = XStart;
+ XStart = XEnd;
+ XEnd = Temp;
+ }
+
+ /* Point to the bitmap address first pixel to draw */
+ ScreenPtr = (uint8_t *) (get_framebuffer()) + XStart + (surface->w * YStart);
+
+ /* Figure out whether we're going left or right, and how far we're going horizontally */
+ if ((XDelta = XEnd - XStart) < 0)
+ {
+ XAdvance = (-1);
+ XDelta = -XDelta;
+ } else {
+ XAdvance = 1;
+ }
+
+ /* Figure out how far we're going vertically */
+ YDelta = YEnd - YStart;
+
+ /* Special cases: Horizontal, vertical, and diagonal lines */
+ if (XDelta == 0)
+ {
+ for (i=0; i <= YDelta; i++)
+ {
+ *ScreenPtr = Color;
+ ScreenPtr += surface->w;
+ }
+
+ UNLOCK_SURFACE_AND_RETURN;
+ }
+ if (YDelta == 0)
+ {
+ for (i=0; i <= XDelta; i++)
+ {
+ *ScreenPtr = Color;
+ ScreenPtr += XAdvance;
+ }
+ UNLOCK_SURFACE_AND_RETURN;
+ }
+ if (XDelta == YDelta)
+ {
+ for (i=0; i <= XDelta; i++)
+ {
+ *ScreenPtr = Color;
+ ScreenPtr += XAdvance + surface->w;
+ }
+ UNLOCK_SURFACE_AND_RETURN;
+ }
+
+ /* Determine whether the line is X or Y major, and handle accordingly */
+ if (XDelta >= YDelta) /* X major line */
+ {
+ WholeStep = XDelta / YDelta;
+ AdjUp = (XDelta % YDelta) * 2;
+ AdjDown = YDelta * 2;
+ ErrorTerm = (XDelta % YDelta) - (YDelta * 2);
+
+ InitialPixelCount = (WholeStep / 2) + 1;
+ FinalPixelCount = InitialPixelCount;
+
+ if ((AdjUp == 0) && ((WholeStep & 0x01) == 0)) InitialPixelCount--;
+ if ((WholeStep & 0x01) != 0) ErrorTerm += YDelta;
+
+ DrawHorizontalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
+
+ for (i=0; i<(YDelta-1); i++)
+ {
+ RunLength = WholeStep;
+ if ((ErrorTerm += AdjUp) > 0)
+ {
+ RunLength ++;
+ ErrorTerm -= AdjDown;
+ }
+
+ DrawHorizontalRun(&ScreenPtr, XAdvance, RunLength, Color);
+ }
+
+ DrawHorizontalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
+
+ UNLOCK_SURFACE_AND_RETURN;
+ } else { /* Y major line */
+ WholeStep = YDelta / XDelta;
+ AdjUp = (YDelta % XDelta) * 2;
+ AdjDown = XDelta * 2;
+ ErrorTerm = (YDelta % XDelta) - (XDelta * 2);
+ InitialPixelCount = (WholeStep / 2) + 1;
+ FinalPixelCount = InitialPixelCount;
+
+ if ((AdjUp == 0) && ((WholeStep & 0x01) == 0)) InitialPixelCount --;
+ if ((WholeStep & 0x01) != 0) ErrorTerm += XDelta;
+
+ DrawVerticalRun(&ScreenPtr, XAdvance, InitialPixelCount, Color);
+
+ for (i=0; i<(XDelta-1); i++)
+ {
+ RunLength = WholeStep;
+ if ((ErrorTerm += AdjUp) > 0)
+ {
+ RunLength ++;
+ ErrorTerm -= AdjDown;
+ }
+
+ DrawVerticalRun(&ScreenPtr, XAdvance, RunLength, Color);
+ }
+
+ DrawVerticalRun(&ScreenPtr, XAdvance, FinalPixelCount, Color);
+ UNLOCK_SURFACE_AND_RETURN;
+ }
+} /* drawline16 */
+
+
+void clear2dscreen(void)
+{
+ SDL_Rect rect;
+
+ rect.x = rect.y = 0;
+ rect.w = surface->w;
+
+ if (qsetmode == 350)
+ rect.h = 350;
+ else if (qsetmode == 480)
+ {
+ if (ydim16 <= 336)
+ rect.h = 336;
+ else
+ rect.h = 480;
+ } /* else if */
+
+ SDL_FillRect(surface, &rect, 0);
+} /* clear2dscreen */
+
+
+void _idle(void)
+{
+ if (surface != NULL)
+ _handle_events();
+ SDL_Delay(1);
+} /* _idle */
+
+void *_getVideoBase(void)
+{
+ return((void *) surface->pixels);
+}
+
+
+//-------------------------------------------------------------------------------------------------
+// TIMER
+//=================================================================================================
+
+
+
+
+// FIX_00007: game speed corrected. The game speed is now as the real
+// DOS duke3d. Unloading a full 200 bullet pistol must take 45.1 sec.
+// SDL timer was not fast/accurate enough and was slowing down the gameplay,
+// so bad
+
+
+static int64_t timerfreq=0;
+static int32_t timerlastsample=0;
+static int timerticspersec=0;
+static void (*usertimercallback)(void) = NULL;
+
+// This timer stuff is all Ken's idea.
+
+//
+// installusertimercallback() -- set up a callback function to be called when the timer is fired
+//
+void (*installusertimercallback(void (*callback)(void)))(void)
+{
+ void (*oldtimercallback)(void);
+
+ oldtimercallback = usertimercallback;
+ usertimercallback = callback;
+
+ return oldtimercallback;
+}
+
+
+/*
+ inittimer() -- initialise timer
+ FCS: The tickspersecond parameter is a ratio value that helps replicating
+ oldschool DOS tick per seconds.
+
+ The way the timer work is:
+ float newSystemTickPerSecond = [0,1]
+ tickPerSecond on a DOS system = tickspersecond * newSystemTickPerSecond ;
+*/
+
+int inittimer(int tickspersecond)
+{
+ int64_t t;
+
+
+ if (timerfreq) return 0; // already installed
+
+ //printf("Initialising timer, with tickPerSecond=%d\n",tickspersecond);
+
+ // OpenWatcom seems to want us to query the value into a local variable
+ // instead of the global 'timerfreq' or else it gets pissed with an
+ // access violation
+ if (!TIMER_GetPlatformTicksInOneSecond(&t)) {
+ printf("Failed fetching timer frequency\n");
+ return -1;
+ }
+ timerfreq = t;
+ timerticspersec = tickspersecond;
+ TIMER_GetPlatformTicks(&t);
+ timerlastsample = (int32_t)(t*timerticspersec / timerfreq);
+
+ usertimercallback = NULL;
+
+ return 0;
+}
+
+//
+// uninittimer() -- shut down timer
+//
+void uninittimer(void)
+{
+ if (!timerfreq) return;
+
+ timerfreq=0;
+ timerticspersec = 0;
+}
+
+//
+// sampletimer() -- update totalclock
+//
+void sampletimer(void)
+{
+ int64_t i;
+ int32_t n;
+
+ if (!timerfreq) return;
+
+ TIMER_GetPlatformTicks(&i);
+
+
+ n = (int32_t)(i*timerticspersec / timerfreq) - timerlastsample;
+ if (n>0) {
+ totalclock += n;
+ timerlastsample += n;
+ }
+
+ if (usertimercallback) for (; n>0; n--) usertimercallback();
+}
+
+
+/*
+ getticks() -- returns the windows ticks count
+ FCS: This seeems to be only used in the multiplayer code
+*/
+uint32_t getticks(void)
+{
+ int64_t i;
+ TIMER_GetPlatformTicks(&i);
+ return (uint32_t)(i*(int32_t)(1000)/timerfreq);
+}
+
+
+//
+// gettimerfreq() -- returns the number of ticks per second the timer is configured to generate
+//
+int gettimerfreq(void)
+{
+ return timerticspersec;
+}
+
+
+
+void initkeys(void)
+{
+ /* does nothing in SDL. Key input handling is set up elsewhere. */
+ /* !!! why not here? */
+}
+
+void uninitkeys(void)
+{
+ /* does nothing in SDL. Key input handling is set up elsewhere. */
+}
+
+
+//unsigned int32_t getticks(void)
+//{
+// return(SDL_GetTicks());
+//} /* getticks */
+
+
+//Timer on windows 98 used to be really poor but now it is very accurate
+// We can just use what SDL uses, no need for QueryPerformanceFrequency or QueryPerformanceCounter
+// (which I bet SDL is using anyway).
+#if 0//PLATFORM_WIN32
+int TIMER_GetPlatformTicksInOneSecond(int64_t* t)
+{
+ QueryPerformanceFrequency((LARGE_INTEGER*)t);
+ return 1;
+}
+
+void TIMER_GetPlatformTicks(int64_t* t)
+{
+ QueryPerformanceCounter((LARGE_INTEGER*)t);
+}
+#else
+//FCS: Let's try to use SDL again: Maybe SDL library is accurate enough now.
+int TIMER_GetPlatformTicksInOneSecond(int64_t* t)
+{
+ *t = 1000;
+ return 1;
+}
+
+void TIMER_GetPlatformTicks(int64_t* t)
+{
+ *t = SDL_GetTicks();
+}
+#endif
+/* end of sdl_driver.c ... */
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/display.h b/apps/plugins/sdl/progs/duke3d/Engine/src/display.h
new file mode 100644
index 0000000000..791d6b9692
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/display.h
@@ -0,0 +1,110 @@
+/*
+ * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * See the included license file "BUILDLIC.TXT" for license info.
+ * This file IS NOT A PART OF Ken Silverman's original release
+ */
+
+#ifndef _INCLUDE_DISPLAY_H_
+#define _INCLUDE_DISPLAY_H_
+
+#include "platform.h"
+
+/* set these in your _platform_init() implementation. */
+int _argc;
+char **_argv;
+
+/* !!! gads, look at all the namespace polution... */
+extern int32_t xres, yres, bytesperline, imageSize, maxpages;
+extern uint8_t *screen, vesachecked;
+extern int32_t buffermode, origbuffermode, linearmode;
+extern uint8_t permanentupdate, vgacompatible;
+extern uint8_t moustat;
+extern int32_t *horizlookup, *horizlookup2, horizycent;
+extern int32_t oxdimen, oviewingrange, oxyaspect;
+extern int32_t curbrightness;
+extern int32_t qsetmode;
+extern int32_t pageoffset, ydim16;
+extern uint8_t* frameplace;
+extern uint8_t* frameoffset;
+extern uint8_t textfont[1024], smalltextfont[1024];
+extern uint8_t pow2char[8];
+extern int32_t stereomode, visualpage, activepage, whiteband, blackband;
+extern int32_t searchx, searchy;
+extern int32_t wx1, wy1, wx2, wy2, ydimen;
+extern int32_t xdimen, xdimenrecip, halfxdimen, xdimenscale, xdimscale;
+
+/*
+ * !!! used to be static. If we ever put the original setgamemode() back, this
+ * !!! can be made static again. --ryan.
+ * !!! (Actually, most of these extern declarations used to be static...rcg.)
+ */
+extern uint8_t permanentlock;
+
+// defined in the game project:
+extern int32_t BFullScreen; // defined in Game\src\config.c
+extern int32_t ScreenMode;
+
+
+/* these need to be implemented by YOUR driver. */
+void _platform_init(int argc, char **argv, const char *title, const char *iconName);
+void _idle(void);
+void _handle_events(void);
+void *_getVideoBase(void);
+void initkeys(void);
+void uninitkeys(void);
+void _nextpage(void);
+void _uninitengine(void);
+void _joystick_init(void);
+void _joystick_deinit(void);
+int _joystick_update(void);
+int _joystick_axis(int axis);
+int _joystick_hat(int hat);
+int _joystick_button(int button);
+
+void getvalidvesamodes(void);
+int VBE_getPalette(int32_t start, int32_t num, uint8_t *dapal);
+int VBE_setPalette(uint8_t *palettebuffer);
+
+
+void setvmode(int mode);
+uint8_t readpixel(uint8_t * location);
+void drawpixel(uint8_t * location, uint8_t pixel);
+
+
+void drawpixel16(int32_t offset);
+void fillscreen16 (int32_t input1, int32_t input2, int32_t input3);
+
+
+void clear2dscreen(void);
+void _updateScreenRect(int32_t x, int32_t y, int32_t w, int32_t h);
+
+/* mouse/keystuff stuff. Also implemented in sdl_driver.c ... */
+int setupmouse(void);
+void readmousexy(short *x, short *y);
+void readmousebstatus(short *bstatus);
+void keyhandler(void);
+uint8_t _readlastkeyhit(void);
+
+/* timer krap. */
+int inittimer(int);
+void uninittimer(void);
+
+/* this is implemented in the game, and your driver calls it. */
+void timerhandler(void);
+
+/* resolution inits. sdl_driver.c ... */
+int32_t _setgamemode(uint8_t davidoption, int32_t daxdim, int32_t daydim);
+
+uint32_t getticks();
+
+void drawline16(int32_t XStart, int32_t YStart, int32_t XEnd, int32_t YEnd, uint8_t Color);
+void setcolor16(uint8_t color);
+
+
+
+void initmultiplayers(uint8_t damultioption, uint8_t dacomrateoption, uint8_t dapriority);
+
+#endif
+
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/draw.c b/apps/plugins/sdl/progs/duke3d/Engine/src/draw.c
new file mode 100644
index 0000000000..bf0fc6828a
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/draw.c
@@ -0,0 +1,919 @@
+// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
+// Ken Silverman's official web site: "http://www.advsys.net/ken"
+// See the included license file "BUILDLIC.TXT" for license info.
+// This file has been modified from Ken Silverman's original release
+
+/* DDOI - This file is an attempt to reimplement a_nasm.asm in C */
+/* FCS: However did that work: This is far from perfect but you have my eternal respect !!! */
+
+#include "platform.h"
+#include "build.h"
+#include "draw.h"
+
+int32_t pixelsAllowed = 10000000000;
+
+uint8_t *transluc = NULL;
+
+static int transrev = 0;
+
+
+#define shrd(a,b,c) (((b)<<(32-(c))) | ((a)>>(c)))
+#define shld(a,b,c) (((b)>>(32-(c))) | ((a)<<(c)))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* --------------- WALLS RENDERING METHOD (USED TO BE HIGHLY OPTIMIZED ASSEMBLY) ----------------------------*/
+extern int32_t asm1;
+extern intptr_t asm2;
+extern uint8_t *asm3;
+extern int32_t asm4;
+
+static uint8_t machxbits_al;
+static uint8_t bitsSetup;
+static uint8_t * textureSetup;
+void sethlinesizes(int32_t i1, int32_t _bits, uint8_t * textureAddress)
+{
+ machxbits_al = i1;
+ bitsSetup = _bits;
+ textureSetup = textureAddress;
+}
+
+
+
+//FCS: Draw ceiling/floors
+//Draw a line from destination in the framebuffer to framebuffer-numPixels
+void hlineasm4(int32_t numPixels, int32_t shade, uint32_t i4, uint32_t i5, uint8_t *dest){
+
+ int32_t shifter = ((256-machxbits_al) & 0x1f);
+ uint32_t source;
+
+ uint8_t * texture = textureSetup;
+ uint8_t bits = bitsSetup;
+
+ shade = shade & 0xffffff00;
+ numPixels++;
+
+ if (!RENDER_DRAW_CEILING_AND_FLOOR)
+ return;
+
+ while (numPixels) {
+
+ source = i5 >> shifter;
+ source = shld(source,i4,bits);
+ source = texture[source];
+
+ if (pixelsAllowed-- > 0)
+ *dest = globalpalwritten[shade|source];
+
+ dest--;
+
+ i5 -= asm1;
+ i4 -= asm2;
+
+ numPixels--;
+
+ }
+}
+
+static int32_t rmach_eax;
+static int32_t rmach_ebx;
+static int32_t rmach_ecx;
+static int32_t rmach_edx;
+static int32_t rmach_esi;
+void setuprhlineasm4(int32_t i1, int32_t i2, int32_t i3, int32_t i4, int32_t i5, int32_t i6)
+{
+ rmach_eax = i1;
+ rmach_ebx = i2;
+ rmach_ecx = i3;
+ rmach_edx = i4;
+ rmach_esi = i5;
+}
+
+
+void rhlineasm4(int32_t i1, uint8_t* texture, int32_t i3, uint32_t i4, uint32_t i5, int32_t dest)
+{
+ uint32_t ebp = dest - i1;
+ uint32_t rmach6b = ebp-1;
+ int32_t numPixels;
+
+ if (i1 <= 0) return;
+
+ numPixels = i1;
+ do {
+
+
+
+ i3 = ((i3&0xffffff00)|(*texture));
+ i4 -= rmach_eax;
+ ebp = (((i4+rmach_eax) < i4) ? -1 : 0);
+ i5 -= rmach_ebx;
+
+ if ((i5 + rmach_ebx) < i5)
+ texture -= (rmach_ecx+1);
+ else
+ texture -= rmach_ecx;
+
+ ebp &= rmach_esi;
+ i1 = ((i1&0xffffff00)|(((uint8_t *)i3)[rmach_edx]));
+
+ if (pixelsAllowed-- > 0)
+ ((uint8_t *)rmach6b)[numPixels] = (i1&0xff);
+
+ texture -= ebp;
+ numPixels--;
+ } while (numPixels);
+}
+
+static int32_t rmmach_eax;
+static int32_t rmmach_ebx;
+static int32_t rmmach_ecx;
+static int32_t rmmach_edx;
+static int32_t setupTileHeight;
+void setuprmhlineasm4(int32_t i1, int32_t i2, int32_t i3, int32_t i4, int32_t tileHeight, int32_t i6)
+{
+ rmmach_eax = i1;
+ rmmach_ebx = i2;
+ rmmach_ecx = i3;
+ rmmach_edx = i4;
+ setupTileHeight = tileHeight;
+}
+
+
+//FCS: ????
+void rmhlineasm4(int32_t i1, intptr_t shade, int32_t colorIndex, int32_t i4, int32_t i5, int32_t dest)
+{
+ uint32_t ebp = dest - i1;
+ uint32_t rmach6b = ebp-1;
+ int32_t numPixels;
+
+ if (i1 <= 0)
+ return;
+
+ numPixels = i1;
+ do {
+
+
+
+ colorIndex = ((colorIndex&0xffffff00)|(*((uint8_t *)shade)));
+ i4 -= rmmach_eax;
+ ebp = (((i4+rmmach_eax) < i4) ? -1 : 0);
+ i5 -= rmmach_ebx;
+
+ if ((i5 + rmmach_ebx) < i5)
+ shade -= (rmmach_ecx+1);
+ else
+ shade -= rmmach_ecx;
+
+ ebp &= setupTileHeight;
+
+ //Check if this colorIndex is the transparent color (255).
+ if ((colorIndex&0xff) != 255) {
+ if (pixelsAllowed-- > 0)
+ {
+ i1 = ((i1&0xffffff00)|(((uint8_t *)colorIndex)[rmmach_edx]));
+ ((uint8_t *)rmach6b)[numPixels] = (i1&0xff);
+ }
+ }
+
+ shade -= ebp;
+ numPixels--;
+
+ } while (numPixels);
+}
+
+
+//Variable used to draw column.
+//This is how much you have to skip in the framebuffer in order to be one pixel below.
+static int32_t bytesperline;
+void setBytesPerLine(int32_t _bytesperline)
+{
+ bytesperline = _bytesperline;
+}
+
+
+
+static uint8_t mach3_al;
+
+//FCS: RENDER TOP AND BOTTOM COLUMN
+int32_t prevlineasm1(int32_t i1, uint8_t* palette, int32_t i3, int32_t i4, uint8_t *source, uint8_t *dest)
+{
+
+
+ if (i3 == 0)
+ {
+ if (!RENDER_DRAW_TOP_AND_BOTTOM_COLUMN)
+ return 0;
+
+ i1 += i4;
+ i4 = ((uint32_t)i4) >> mach3_al;
+ i4 = (i4&0xffffff00) | source[i4];
+
+ if (pixelsAllowed-- > 0)
+ *dest = palette[i4];
+
+
+
+ return i1;
+ } else {
+ return vlineasm1(i1,palette,i3,i4,source,dest);
+ }
+}
+
+
+//FCS: This is used to draw wall border vertical lines
+int32_t vlineasm1(int32_t vince, uint8_t* palookupoffse, int32_t numPixels, int32_t vplce, uint8_t* texture, uint8_t* dest)
+{
+ uint32_t temp;
+
+ if (!RENDER_DRAW_WALL_BORDERS)
+ return vplce;
+
+ numPixels++;
+ while (numPixels)
+ {
+ temp = ((uint32_t)vplce) >> mach3_al;
+
+ temp = texture[temp];
+
+ if (pixelsAllowed-- > 0)
+ *dest = palookupoffse[temp];
+
+ vplce += vince;
+ dest += bytesperline;
+ numPixels--;
+ }
+ return vplce;
+}
+
+
+int32_t tvlineasm1(int32_t i1, uint8_t * texture, int32_t numPixels, int32_t i4, uint8_t *source, uint8_t *dest)
+{
+ uint8_t shiftValue = (globalshiftval & 0x1f);
+
+ numPixels++;
+ while (numPixels)
+ {
+ uint32_t temp = i4;
+ temp >>= shiftValue;
+ temp = source[temp];
+
+ //255 is the index for transparent color index. Skip drawing this pixel.
+ if (temp != 255)
+ {
+ uint16_t colorIndex;
+
+ colorIndex = texture[temp];
+ colorIndex |= ((*dest)<<8);
+
+ if (transrev)
+ colorIndex = ((colorIndex>>8)|(colorIndex<<8));
+
+ if (pixelsAllowed-- > 0)
+ *dest = transluc[colorIndex];
+ }
+
+ i4 += i1;
+
+ //We are drawing a column ?!
+ dest += bytesperline;
+ numPixels--;
+ }
+ return i4;
+} /* tvlineasm1 */
+
+
+static uint8_t tran2shr;
+static uint32_t tran2pal_ebx;
+static uint32_t tran2pal_ecx;
+void setuptvlineasm2(int32_t i1, int32_t i2, int32_t i3)
+{
+ tran2shr = (i1&0x1f);
+ tran2pal_ebx = i2;
+ tran2pal_ecx = i3;
+} /* */
+
+
+void tvlineasm2(uint32_t i1, uint32_t i2, uintptr_t i3, uintptr_t i4, uint32_t i5, uintptr_t i6)
+{
+ uint32_t ebp = i1;
+ uint32_t tran2inca = i2;
+ uint32_t tran2incb = asm1;
+ uintptr_t tran2bufa = i3;
+ uintptr_t tran2bufb = i4;
+ uintptr_t tran2edi = asm2;
+ uintptr_t tran2edi1 = asm2 + 1;
+
+ i6 -= asm2;
+
+ do {
+
+ i1 = i5 >> tran2shr;
+ i2 = ebp >> tran2shr;
+ i5 += tran2inca;
+ ebp += tran2incb;
+ i3 = ((uint8_t *)tran2bufa)[i1];
+ i4 = ((uint8_t *)tran2bufb)[i2];
+ if (i3 == 255) { // skipdraw1
+ if (i4 != 255) { // skipdraw3
+ uint16_t val;
+ val = ((uint8_t *)tran2pal_ecx)[i4];
+ val |= (((uint8_t *)i6)[tran2edi1]<<8);
+
+ if (transrev)
+ val = ((val>>8)|(val<<8));
+
+ if (pixelsAllowed-- > 0)
+ ((uint8_t *)i6)[tran2edi1] = transluc[val];
+ }
+ } else if (i4 == 255) { // skipdraw2
+ uint16_t val;
+ val = ((uint8_t *)tran2pal_ebx)[i3];
+ val |= (((uint8_t *)i6)[tran2edi]<<8);
+
+ if (transrev)
+ val = ((val>>8)|(val<<8));
+
+ if (pixelsAllowed-- > 0)
+ ((uint8_t *)i6)[tran2edi] = transluc[val];
+ } else {
+ uint16_t l = ((uint8_t *)i6)[tran2edi]<<8;
+ uint16_t r = ((uint8_t *)i6)[tran2edi1]<<8;
+ l |= ((uint8_t *)tran2pal_ebx)[i3];
+ r |= ((uint8_t *)tran2pal_ecx)[i4];
+ if (transrev) {
+ l = ((l>>8)|(l<<8));
+ r = ((r>>8)|(r<<8));
+ }
+ if (pixelsAllowed-- > 0)
+ {
+ ((uint8_t *)i6)[tran2edi] = transluc[l];
+ ((uint8_t *)i6)[tran2edi1] =transluc[r];
+ pixelsAllowed--;
+ }
+ }
+ i6 += bytesperline;
+ } while (i6 > i6 - bytesperline);
+ asm1 = i5;
+ asm2 = ebp;
+}
+
+
+
+static uint8_t machmv;
+int32_t mvlineasm1(int32_t vince, uint8_t* palookupoffse, int32_t i3, int32_t vplce, uint8_t* texture, uint8_t *dest)
+{
+ uint32_t temp;
+
+ for(;i3>=0;i3--)
+ {
+ temp = ((uint32_t)vplce) >> machmv;
+ temp = texture[temp];
+
+ if (temp != 255)
+ {
+ if (pixelsAllowed-- > 0)
+ *dest = palookupoffse[temp];
+ }
+
+ vplce += vince;
+ dest += bytesperline;
+ }
+ return vplce;
+}
+
+
+void setupvlineasm(int32_t i1)
+{
+ mach3_al = (i1&0x1f);
+}
+
+//FCS This is used to fill the inside of a wall (so it draws VERTICAL column, always).
+void vlineasm4(int32_t columnIndex, intptr_t framebuffer)
+{
+
+ if (!RENDER_DRAW_WALL_INSIDE)
+ return ;
+
+ int i;
+ uint32_t temp;
+
+ uintptr_t index = (framebuffer + ylookup[columnIndex]);
+ uint8_t *dest= (uint8_t *)(-ylookup[columnIndex]);
+
+ do {
+ for (i = 0; i < 4; i++)
+ {
+
+ temp = ((uint32_t)vplce[i]) >> mach3_al;
+ temp = (((uint8_t *)(bufplce[i]))[temp]);
+
+ if (pixelsAllowed-- > 0)
+ dest[index+i] = palookupoffse [i] [temp];
+
+ vplce[i] += vince[i];
+ }
+ dest += bytesperline;
+ } while (((uint32_t)dest - bytesperline) < ((uint32_t)dest));
+}
+
+
+void setupmvlineasm(int32_t i1)
+{
+ //Only keep 5 first bits
+ machmv = (i1&0x1f);
+}
+
+
+void mvlineasm4(int32_t column, intptr_t framebufferOffset)
+{
+ int i;
+ uint32_t temp;
+ uintptr_t index = (framebufferOffset + ylookup[column]);
+ uint8_t *dest = (uint8_t *)(-ylookup[column]);
+
+ do {
+
+ if (pixelsAllowed <= 0)
+ return;
+
+ for (i = 0; i < 4; i++)
+ {
+
+ temp = ((uint32_t)vplce[i]) >> machmv;
+ temp = (((uint8_t *)(bufplce[i]))[temp]);
+ if (temp != 255)
+ {
+ if (pixelsAllowed-- > 0)
+ dest[index+i] = palookupoffse[i][temp];
+ }
+ vplce[i] += vince[i];
+ }
+ dest += bytesperline;
+
+ } while (((uint32_t)dest - bytesperline) < ((uint32_t)dest));
+}
+/* END --------------- WALLS RENDERING METHOD (USED TO BE HIGHLY OPTIMIZED ASSEMBLY) ----------------------------*/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* --------------- SPRITE RENDERING METHOD (USED TO BE HIGHLY OPTIMIZED ASSEMBLY) ----------------------------*/
+static int32_t spal_eax;
+static int32_t smach_eax;
+static int32_t smach2_eax;
+static int32_t smach5_eax;
+static int32_t smach_ecx;
+void setupspritevline(int32_t i1, int32_t i2, int32_t i3, int32_t i4, int32_t i5, int32_t i6)
+{
+ spal_eax = i1;
+ smach_eax = (i5<<16);
+ smach2_eax = (i5>>16)+i2;
+ smach5_eax = smach2_eax + i4;
+ smach_ecx = i3;
+}
+
+
+void spritevline(int32_t i1, uint32_t i2, int32_t i3, uint32_t i4, uint8_t* source, uint8_t* dest)
+{
+
+
+setup:
+
+ i2 += smach_eax;
+ i1 = (i1&0xffffff00) | (*source&0xff);
+ if ((i2 - smach_eax) > i2)
+ source += smach2_eax + 1;
+ else
+ source += smach2_eax;
+
+ while(1) {
+
+ i1 = (i1&0xffffff00) | (((uint8_t *)spal_eax)[i1]&0xff);
+
+ if (pixelsAllowed-- > 0)
+ *dest = i1;
+
+ dest += bytesperline;
+
+ i4 += smach_ecx;
+ i4--;
+ if (!((i4 - smach_ecx) > i4) && i4 != 0)
+ goto setup;
+
+ if (i4 == 0)
+ return;
+
+ i2 += smach_eax;
+
+ i1 = (i1&0xffffff00) | (*source&0xff);
+
+ if ((i2 - smach_eax) > i2)
+ source += smach5_eax + 1;
+ else
+ source += smach5_eax;
+ }
+}
+
+
+static int32_t mspal_eax;
+static int32_t msmach_eax;
+static int32_t msmach2_eax;
+static int32_t msmach5_eax;
+static int32_t msmach_ecx;
+void msetupspritevline(int32_t i1, int32_t i2, int32_t i3, int32_t i4, int32_t i5, int32_t i6)
+{
+ mspal_eax = i1;
+ msmach_eax = (i5<<16);
+ msmach2_eax = (i5>>16)+i2;
+ msmach5_eax = smach2_eax + i4;
+ msmach_ecx = i3;
+}
+
+
+void mspritevline(int32_t colorIndex, int32_t i2, int32_t i3, int32_t i4, uint8_t * source, uint8_t * dest)
+{
+
+setup:
+ i2 += smach_eax;
+
+ colorIndex = (colorIndex&0xffffff00) | (*source&0xff);
+
+ if ((i2 - smach_eax) > i2)
+ source += smach2_eax + 1;
+ else
+ source += smach2_eax;
+
+ while(1){
+
+ //Skip transparent pixels (index=255)
+ if ((colorIndex&0xff) != 255)
+ {
+ colorIndex = (colorIndex&0xffffff00) | (((uint8_t *)spal_eax)[colorIndex]&0xff);
+
+ if (pixelsAllowed-- > 0)
+ *dest = colorIndex;
+ }
+
+ dest += bytesperline;
+ i4 += smach_ecx;
+ i4--;
+
+ if (!((i4 - smach_ecx) > i4) && i4 != 0)
+ goto setup;
+
+ if (i4 == 0)
+ return;
+
+ i2 += smach_eax;
+
+ colorIndex = (colorIndex&0xffffff00) | (*source&0xff);
+
+ if ((i2 - smach_eax) > i2)
+ source += smach5_eax + 1;
+ else
+ source += smach5_eax;
+ }
+}
+
+
+uint8_t * tspal;
+uint32_t tsmach_eax1;
+uint32_t adder;
+uint32_t tsmach_eax3;
+uint32_t tsmach_ecx;
+void tsetupspritevline(uint8_t * palette, int32_t i2, int32_t i3, int32_t i4, int32_t i5)
+{
+ tspal = palette;
+ tsmach_eax1 = i5 << 16;
+ adder = (i5 >> 16) + i2;
+ tsmach_eax3 = adder + i4;
+ tsmach_ecx = i3;
+}
+
+
+/*
+ FCS: Draw a sprite vertical line of pixels.
+ */
+void DrawSpriteVerticalLine(int32_t i2, int32_t numPixels, uint32_t i4, uint8_t * texture, uint8_t * dest)
+{
+ uint8_t colorIndex;
+
+ while (numPixels)
+ {
+ numPixels--;
+
+ if (numPixels != 0)
+ {
+
+ i4 += tsmach_ecx;
+
+ if (i4 < (i4 - tsmach_ecx))
+ adder = tsmach_eax3;
+
+ colorIndex = *texture;
+
+ i2 += tsmach_eax1;
+ if (i2 < (i2 - tsmach_eax1))
+ texture++;
+
+ texture += adder;
+
+ //255 is the index of the transparent color: Do not draw it.
+ if (colorIndex != 255)
+ {
+ uint16_t val;
+ val = tspal[colorIndex];
+ val |= (*dest)<<8;
+
+ if (transrev)
+ val = ((val>>8)|(val<<8));
+
+ colorIndex = transluc[val];
+
+ if (pixelsAllowed-- > 0)
+ *dest = colorIndex;
+ }
+
+ //Move down one pixel on the framebuffer
+ dest += bytesperline;
+ }
+
+
+ }
+}
+/* END--------------- SPRITE RENDERING METHOD (USED TO BE HIGHLY OPTIMIZED ASSEMBLY) ----------------------------*/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* --------------- FLOOR/CEILING RENDERING METHOD (USED TO BE HIGHLY OPTIMIZED ASSEMBLY) ----------------------------*/
+
+void settrans(int32_t type){
+ transrev = type;
+}
+
+static uint8_t * textureData;
+static uint8_t * mmach_asm3;
+static int32_t mmach_asm1;
+static int32_t mmach_asm2;
+
+void mhline(uint8_t * texture, int32_t i2, int32_t numPixels, int32_t i4, int32_t i5, uint8_t* dest)
+{
+ textureData = texture;
+ mmach_asm3 = asm3;
+ mmach_asm1 = asm1;
+ mmach_asm2 = asm2;
+ mhlineskipmodify(i2,numPixels>>16,i5,dest);
+}
+
+
+static uint8_t mshift_al = 26;
+static uint8_t mshift_bl = 6;
+void mhlineskipmodify( uint32_t i2, int32_t numPixels, int32_t i5, uint8_t* dest)
+{
+ uint32_t ebx;
+ int32_t colorIndex;
+
+ while (numPixels >= 0)
+ {
+ ebx = i2 >> mshift_al;
+ ebx = shld (ebx, (uint32_t)i5, mshift_bl);
+ colorIndex = textureData[ebx];
+
+ //Skip transparent color.
+ if ((colorIndex&0xff) != 0xff){
+ if (pixelsAllowed-- > 0)
+ *dest = mmach_asm3[colorIndex];
+ }
+ i2 += mmach_asm1;
+ i5 += mmach_asm2;
+ dest++;
+ numPixels--;
+
+
+ }
+}
+
+
+void msethlineshift(int32_t i1, int32_t i2)
+{
+ i1 = 256-i1;
+ mshift_al = (i1&0x1f);
+ mshift_bl = (i2&0x1f);
+} /* msethlineshift */
+
+
+static uint8_t * tmach_eax;
+static uint8_t * tmach_asm3;
+static int32_t tmach_asm1;
+static int32_t tmach_asm2;
+
+void thline(uint8_t * i1, int32_t i2, int32_t i3, int32_t i4, int32_t i5, uint8_t * i6)
+{
+ tmach_eax = i1;
+ tmach_asm3 = asm3;
+ tmach_asm1 = asm1;
+ tmach_asm2 = asm2;
+ thlineskipmodify(asm2,i2,i3,i4,i5,i6);
+}
+
+static uint8_t tshift_al = 26;
+static uint8_t tshift_bl = 6;
+void thlineskipmodify(int32_t i1, uint32_t i2, uint32_t i3, int32_t i4, int32_t i5, uint8_t * i6)
+{
+ uint32_t ebx;
+ int counter = (i3>>16);
+ while (counter >= 0)
+ {
+ ebx = i2 >> tshift_al;
+ ebx = shld (ebx, (uint32_t)i5, tshift_bl);
+ i1 = tmach_eax[ebx];
+ if ((i1&0xff) != 0xff)
+ {
+ uint16_t val = tmach_asm3[i1];
+ val |= (*i6)<<8;
+
+ if (transrev)
+ val = ((val>>8)|(val<<8));
+
+ if (pixelsAllowed-- > 0)
+ *i6 = transluc[val];
+ }
+
+ i2 += tmach_asm1;
+ i5 += tmach_asm2;
+ i6++;
+ counter--;
+
+
+ }
+}
+
+
+void tsethlineshift(int32_t i1, int32_t i2)
+{
+ i1 = 256-i1;
+ tshift_al = (i1&0x1f);
+ tshift_bl = (i2&0x1f);
+}
+
+
+
+
+static intptr_t slopemach_ebx;
+static int32_t slopemach_ecx;
+static int32_t slopemach_edx;
+static uint8_t slopemach_ah1;
+static uint8_t slopemach_ah2;
+static float asm2_f;
+typedef union { unsigned int i; float f; } bitwisef2i;
+void setupslopevlin(int32_t i1, intptr_t i2, int32_t i3)
+{
+ bitwisef2i c;
+ slopemach_ebx = i2;
+ slopemach_ecx = i3;
+ slopemach_edx = (1<<(i1&0x1f)) - 1;
+ slopemach_edx <<= ((i1&0x1f00)>>8);
+ slopemach_ah1 = 32-((i1&0x1f00)>>8);
+ slopemach_ah2 = (slopemach_ah1 - (i1&0x1f)) & 0x1f;
+ c.f = asm2_f = (float)asm1;
+ asm2 = c.i;
+}
+
+extern int32_t reciptable[2048];
+extern int32_t globalx3, globaly3;
+extern int32_t fpuasm;
+#define low32(a) ((a&0xffffffff))
+#define high32(a) ((int)(((__int64)a&(__int64)0xffffffff00000000)>>32))
+
+//FCS: Render RENDER_SLOPPED_CEILING_AND_FLOOR
+void slopevlin(intptr_t i1, uint32_t i2, int32_t i3, int32_t i4, int32_t i5, int32_t i6)
+{
+ bitwisef2i c;
+ uint32_t ecx,eax,ebx,edx,esi,edi;
+//This is so bad to cast asm3 to int then float :( !!!
+ float a = (float)(int32_t) asm3 + asm2_f;
+ i1 -= slopemach_ecx;
+ esi = i5 + low32((__int64)globalx3 * (__int64)(i2<<3));
+ edi = i6 + low32((__int64)globaly3 * (__int64)(i2<<3));
+ ebx = i4;
+
+ if (!RENDER_SLOPPED_CEILING_AND_FLOOR)
+ return;
+
+ do {
+ // -------------
+ // All this is calculating a fixed point approx. of 1/a
+ c.f = a;
+ fpuasm = eax = c.i;
+ edx = (((int32_t)eax) < 0) ? 0xffffffff : 0;
+ eax = eax << 1;
+ ecx = (eax>>24); // exponent
+ eax = ((eax&0xffe000)>>11);
+ ecx = ((ecx&0xffffff00)|((ecx-2)&0xff));
+ eax = reciptable[eax/4];
+ eax >>= (ecx&0x1f);
+ eax ^= edx;
+ // -------------
+ edx = i2;
+ i2 = eax;
+ eax -= edx;
+ ecx = low32((__int64)globalx3 * (__int64)eax);
+ eax = low32((__int64)globaly3 * (__int64)eax);
+ a += asm2_f;
+
+ asm4 = ebx;
+ ecx = ((ecx&0xffffff00)|(ebx&0xff));
+ if (ebx >= 8) ecx = ((ecx&0xffffff00)|8);
+
+ ebx = esi;
+ edx = edi;
+ while ((ecx&0xff))
+ {
+ ebx >>= slopemach_ah2;
+ esi += ecx;
+ edx >>= slopemach_ah1;
+ ebx &= slopemach_edx;
+ edi += eax;
+ i1 += slopemach_ecx;
+ edx = ((edx&0xffffff00)|((((uint8_t *)(ebx+edx))[slopemach_ebx])));
+ ebx = *((uint32_t*)i3); // register trickery
+ i3 -= 4;
+ eax = ((eax&0xffffff00)|(*((uint8_t *)(ebx+edx))));
+ ebx = esi;
+
+ if (pixelsAllowed-- > 0)
+ *((uint8_t *)i1) = (eax&0xff);
+
+ edx = edi;
+ ecx = ((ecx&0xffffff00)|((ecx-1)&0xff));
+
+
+ }
+ ebx = asm4;
+ ebx -= 8; // BITSOFPRECISIONPOW
+
+
+
+ } while ((int32_t)ebx > 0);
+}
+
+
+/* END --------------- FLOOR/CEILING RENDERING METHOD (USED TO BE HIGHLY OPTIMIZED ASSEMBLY) ----------------------------*/
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/draw.h b/apps/plugins/sdl/progs/duke3d/Engine/src/draw.h
new file mode 100644
index 0000000000..0f2a656b6a
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/draw.h
@@ -0,0 +1,105 @@
+/*
+ * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * See the included license file "BUILDLIC.TXT" for license info.
+ * This file IS NOT A PART OF Ken Silverman's original release
+ */
+
+#ifndef _INCLUDE_A_H_
+#define _INCLUDE_A_H_
+
+#ifdef _WIN32
+ #include "windows/inttypes.h"
+#else
+ #include <inttypes.h>
+#endif
+
+
+//C++ linker friendly
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+extern uint8_t *transluc;
+
+
+extern uint8_t *globalpalwritten;
+extern int16_t globalshiftval;
+extern int32_t vplce[4], vince[4];
+extern intptr_t bufplce[4];
+extern uint8_t* palookupoffse[4];
+
+void sethlinesizes(int32_t,int32_t,uint8_t *);
+
+
+void hlineasm4(int32_t,int32_t,uint32_t,uint32_t,uint8_t*);
+void setuprhlineasm4(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
+void rhlineasm4(int32_t,uint8_t*,int32_t,uint32_t,uint32_t,int32_t);
+void setuprmhlineasm4(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
+void rmhlineasm4(int32_t,intptr_t,int32_t,int32_t,int32_t,int32_t);
+
+
+void setBytesPerLine(int32_t);
+
+int32_t prevlineasm1(int32_t,uint8_t* palette ,int32_t,int32_t,uint8_t *,uint8_t *);
+int32_t vlineasm1(int32_t,uint8_t*,int32_t,int32_t,uint8_t *,uint8_t*);
+
+int32_t tvlineasm1(int32_t,uint8_t *,int32_t,int32_t,uint8_t *,uint8_t * dest);
+void setuptvlineasm2(int32_t,int32_t,int32_t);
+void tvlineasm2(uint32_t,uint32_t,uintptr_t,uintptr_t,uint32_t,uintptr_t);
+int32_t mvlineasm1(int32_t,uint8_t*,int32_t,int32_t,uint8_t* texture,uint8_t* dest);
+void setupvlineasm(int32_t);
+void vlineasm4(int32_t,intptr_t);
+void setupmvlineasm(int32_t);
+void mvlineasm4(int32_t,intptr_t);
+void setupspritevline(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
+void spritevline(int32_t,uint32_t,int32_t,uint32_t,uint8_t*,uint8_t*);
+void msetupspritevline(int32_t,int32_t,int32_t,int32_t,int32_t,int32_t);
+void mspritevline(int32_t,int32_t,int32_t,int32_t,uint8_t *,uint8_t *);
+void tsetupspritevline(uint8_t *,int32_t,int32_t,int32_t,int32_t);
+void DrawSpriteVerticalLine(int32_t,int32_t,uint32_t,uint8_t* ,uint8_t*);
+void mhline(uint8_t *,int32_t,int32_t,int32_t,int32_t,uint8_t*);
+void mhlineskipmodify(uint32_t,int32_t,int32_t,uint8_t*);
+void msethlineshift(int32_t,int32_t);
+void thline(uint8_t*,int32_t,int32_t,int32_t,int32_t,uint8_t *);
+void thlineskipmodify(int32_t,uint32_t,uint32_t,int32_t,int32_t,uint8_t *);
+void tsethlineshift(int32_t,int32_t);
+void setupslopevlin(int32_t,intptr_t,int32_t);
+void slopevlin(intptr_t,uint32_t,int32_t,int32_t,int32_t,int32_t);
+
+
+#define TRANS_NORMAL 0
+#define TRANS_REVERSE 1
+void settrans(int32_t type);
+
+
+
+
+
+//FCS: In order to see how the engine renders different part of the screen you can set the following macros
+//VISUALIZE RENDERER
+
+#define MAX_PIXEL_RENDERERED ((1600*1200)+20000 )
+extern int32_t pixelsAllowed;
+
+#define RENDER_DRAW_WALL_BORDERS 1
+#define RENDER_DRAW_WALL_INSIDE 1
+#define RENDER_DRAW_CEILING_AND_FLOOR 1
+#define RENDER_DRAW_TOP_AND_BOTTOM_COLUMN 1
+#define RENDER_SLOPPED_CEILING_AND_FLOOR 1
+
+#if RENDER_DRAW_WALL_BORDERS && RENDER_DRAW_WALL_INSIDE && RENDER_DRAW_CEILING_AND_FLOOR && RENDER_DRAW_TOP_AND_BOTTOM_COLUMN && RENDER_SLOPPED_CEILING_AND_FLOOR && MAX_PIXEL_RENDERERED!=0
+ #define CLEAR_FRAMEBUFFER 0
+#else
+ #define CLEAR_FRAMEBUFFER 1
+#endif
+//END VISUALIZE RENDERER
+
+
+//C++
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/dummy_multi.c b/apps/plugins/sdl/progs/duke3d/Engine/src/dummy_multi.c
new file mode 100644
index 0000000000..c9cef1f4ab
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/dummy_multi.c
@@ -0,0 +1,16 @@
+//
+// dummy.c
+// Duke3D
+//
+// Created by fabien sanglard on 12-12-12.
+// Copyright (c) 2012 fabien sanglard. All rights reserved.
+//
+
+#include "build.h"
+
+
+short numplayers = 1, myconnectindex = 0;
+short connecthead, connectpoint2[MAXPLAYERS];
+
+
+//uint8_t syncstate=0;
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/ChangeLog b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/ChangeLog
new file mode 100644
index 0000000000..9386a01bf0
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/ChangeLog
@@ -0,0 +1,177 @@
+ENet 1.3.13 (April 30, 2015):
+
+* miscellaneous bug fixes
+* added premake and cmake support
+* miscellaneous documentation cleanups
+
+ENet 1.3.12 (April 24, 2014):
+
+* added maximumPacketSize and maximumWaitingData fields to ENetHost to limit the amount of
+data waiting to be delivered on a peer (beware that the default maximumPacketSize is
+32MB and should be set higher if desired as should maximumWaitingData)
+
+ENet 1.3.11 (December 26, 2013):
+
+* allow an ENetHost to connect to itself
+* fixed possible bug with disconnect notifications during connect attempts
+* fixed some preprocessor definition bugs
+
+ENet 1.3.10 (October 23, 2013);
+
+* doubled maximum reliable window size
+* fixed RCVTIMEO/SNDTIMEO socket options and also added NODELAY
+
+ENet 1.3.9 (August 19, 2013):
+
+* added duplicatePeers option to ENetHost which can limit the number of peers from duplicate IPs
+* added enet_socket_get_option() and ENET_SOCKOPT_ERROR
+* added enet_host_random_seed() platform stub
+
+ENet 1.3.8 (June 2, 2013):
+
+* added enet_linked_version() for checking the linked version
+* added enet_socket_get_address() for querying the local address of a socket
+* silenced some debugging prints unless ENET_DEBUG is defined during compilation
+* handle EINTR in enet_socket_wait() so that enet_host_service() doesn't propagate errors from signals
+* optimized enet_host_bandwidth_throttle() to be less expensive for large numbers of peers
+
+ENet 1.3.7 (March 6, 2013):
+
+* added ENET_PACKET_FLAG_SENT to indicate that a packet is being freed because it has been sent
+* added userData field to ENetPacket
+* changed how random seed is generated on Windows to avoid import warnings
+* fixed case where disconnects could be generated with no preceding connect event
+
+ENet 1.3.6 (December 11, 2012):
+
+* added support for intercept callback in ENetHost that can be used to process raw packets before ENet
+* added enet_socket_shutdown() for issuing shutdown on a socket
+* fixed enet_socket_connect() to not error on non-blocking connects
+* fixed bug in MTU negotiation during connections
+
+ENet 1.3.5 (July 31, 2012):
+
+* fixed bug in unreliable packet fragment queuing
+
+ENet 1.3.4 (May 29, 2012):
+
+* added enet_peer_ping_interval() for configuring per-peer ping intervals
+* added enet_peer_timeout() for configuring per-peer timeouts
+* added protocol packet size limits
+
+ENet 1.3.3 (June 28, 2011):
+
+* fixed bug with simultaneous disconnects not dispatching events
+
+ENet 1.3.2 (May 31, 2011):
+
+* added support for unreliable packet fragmenting via the packet flag
+ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT
+* fixed regression in unreliable packet queuing
+* added check against received port to limit some forms of IP-spoofing
+
+ENet 1.3.1 (February 10, 2011):
+
+* fixed bug in tracking of reliable data in transit
+* reliable data window size now scales with the throttle
+* fixed bug in fragment length calculation when checksums are used
+
+ENet 1.3.0 (June 5, 2010):
+
+* enet_host_create() now requires the channel limit to be specified as
+a parameter
+* enet_host_connect() now accepts a data parameter which is supplied
+to the receiving receiving host in the event data field for a connect event
+* added an adaptive order-2 PPM range coder as a built-in compressor option
+which can be set with enet_host_compress_with_range_coder()
+* added support for packet compression configurable with a callback
+* improved session number handling to not rely on the packet checksum
+field, saving 4 bytes per packet unless the checksum option is used
+* removed the dependence on the rand callback for session number handling
+
+Caveats: This version is not protocol compatible with the 1.2 series or
+earlier. The enet_host_connect and enet_host_create API functions require
+supplying additional parameters.
+
+ENet 1.2.5 (June 28, 2011):
+
+* fixed bug with simultaneous disconnects not dispatching events
+
+ENet 1.2.4 (May 31, 2011):
+
+* fixed regression in unreliable packet queuing
+* added check against received port to limit some forms of IP-spoofing
+
+ENet 1.2.3 (February 10, 2011):
+
+* fixed bug in tracking reliable data in transit
+
+ENet 1.2.2 (June 5, 2010):
+
+* checksum functionality is now enabled by setting a checksum callback
+inside ENetHost instead of being a configure script option
+* added totalSentData, totalSentPackets, totalReceivedData, and
+totalReceivedPackets counters inside ENetHost for getting usage
+statistics
+* added enet_host_channel_limit() for limiting the maximum number of
+channels allowed by connected peers
+* now uses dispatch queues for event dispatch rather than potentially
+unscalable array walking
+* added no_memory callback that is called when a malloc attempt fails,
+such that if no_memory returns rather than aborts (the default behavior),
+then the error is propagated to the return value of the API calls
+* now uses packed attribute for protocol structures on platforms with
+strange alignment rules
+* improved autoconf build system contributed by Nathan Brink allowing
+for easier building as a shared library
+
+Caveats: If you were using the compile-time option that enabled checksums,
+make sure to set the checksum callback inside ENetHost to enet_crc32 to
+regain the old behavior. The ENetCallbacks structure has added new fields,
+so make sure to clear the structure to zero before use if
+using enet_initialize_with_callbacks().
+
+ENet 1.2.1 (November 12, 2009):
+
+* fixed bug that could cause disconnect events to be dropped
+* added thin wrapper around select() for portable usage
+* added ENET_SOCKOPT_REUSEADDR socket option
+* factored enet_socket_bind()/enet_socket_listen() out of enet_socket_create()
+* added contributed Code::Blocks build file
+
+ENet 1.2 (February 12, 2008):
+
+* fixed bug in VERIFY_CONNECT acknowledgement that could cause connect
+attempts to occasionally timeout
+* fixed acknowledgements to check both the outgoing and sent queues
+when removing acknowledged packets
+* fixed accidental bit rot in the MSVC project file
+* revised sequence number overflow handling to address some possible
+disconnect bugs
+* added enet_host_check_events() for getting only local queued events
+* factored out socket option setting into enet_socket_set_option() so
+that socket options are now set separately from enet_socket_create()
+
+Caveats: While this release is superficially protocol compatible with 1.1,
+differences in the sequence number overflow handling can potentially cause
+random disconnects.
+
+ENet 1.1 (June 6, 2007):
+
+* optional CRC32 just in case someone needs a stronger checksum than UDP
+provides (--enable-crc32 configure option)
+* the size of packet headers are half the size they used to be (so less
+overhead when sending small packets)
+* enet_peer_disconnect_later() that waits till all queued outgoing
+packets get sent before issuing an actual disconnect
+* freeCallback field in individual packets for notification of when a
+packet is about to be freed
+* ENET_PACKET_FLAG_NO_ALLOCATE for supplying pre-allocated data to a
+packet (can be used in concert with freeCallback to support some custom
+allocation schemes that the normal memory allocation callbacks would
+normally not allow)
+* enet_address_get_host_ip() for printing address numbers
+* promoted the enet_socket_*() functions to be part of the API now
+* a few stability/crash fixes
+
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/LICENSE b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/LICENSE
new file mode 100644
index 0000000000..436053efda
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/LICENSE
@@ -0,0 +1,7 @@
+Copyright (c) 2002-2015 Lee Salzman
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/README b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/README
new file mode 100644
index 0000000000..54b2d21304
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/README
@@ -0,0 +1,15 @@
+Please visit the ENet homepage at http://enet.bespin.org for installation
+and usage instructions.
+
+If you obtained this package from github, the quick description on how to build
+is:
+
+# Generate the build system.
+
+autoreconf -vfi
+
+# Compile and install the library.
+
+./configure && make && make install
+
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/callbacks.h b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/callbacks.h
new file mode 100644
index 0000000000..340a4a9896
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/callbacks.h
@@ -0,0 +1,27 @@
+/**
+ @file callbacks.h
+ @brief ENet callbacks
+*/
+#ifndef __ENET_CALLBACKS_H__
+#define __ENET_CALLBACKS_H__
+
+#include <stdlib.h>
+
+typedef struct _ENetCallbacks
+{
+ void * (ENET_CALLBACK * malloc) (size_t size);
+ void (ENET_CALLBACK * free) (void * memory);
+ void (ENET_CALLBACK * no_memory) (void);
+} ENetCallbacks;
+
+/** @defgroup callbacks ENet internal callbacks
+ @{
+ @ingroup private
+*/
+extern void * enet_malloc (size_t);
+extern void enet_free (void *);
+
+/** @} */
+
+#endif /* __ENET_CALLBACKS_H__ */
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/enet.h b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/enet.h
new file mode 100644
index 0000000000..ac1ca8636a
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/enet.h
@@ -0,0 +1,592 @@
+/**
+ @file enet.h
+ @brief ENet public header file
+*/
+#ifndef __ENET_ENET_H__
+#define __ENET_ENET_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include "win32.h"
+#else
+#include "unix.h"
+#endif
+
+#include "types.h"
+#include "protocol.h"
+#include "list.h"
+#include "callbacks.h"
+
+#define ENET_VERSION_MAJOR 1
+#define ENET_VERSION_MINOR 3
+#define ENET_VERSION_PATCH 13
+#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch))
+#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF)
+#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF)
+#define ENET_VERSION_GET_PATCH(version) ((version)&0xFF)
+#define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH)
+
+typedef enet_uint32 ENetVersion;
+
+struct _ENetHost;
+struct _ENetEvent;
+struct _ENetPacket;
+
+typedef enum _ENetSocketType
+{
+ ENET_SOCKET_TYPE_STREAM = 1,
+ ENET_SOCKET_TYPE_DATAGRAM = 2
+} ENetSocketType;
+
+typedef enum _ENetSocketWait
+{
+ ENET_SOCKET_WAIT_NONE = 0,
+ ENET_SOCKET_WAIT_SEND = (1 << 0),
+ ENET_SOCKET_WAIT_RECEIVE = (1 << 1),
+ ENET_SOCKET_WAIT_INTERRUPT = (1 << 2)
+} ENetSocketWait;
+
+typedef enum _ENetSocketOption
+{
+ ENET_SOCKOPT_NONBLOCK = 1,
+ ENET_SOCKOPT_BROADCAST = 2,
+ ENET_SOCKOPT_RCVBUF = 3,
+ ENET_SOCKOPT_SNDBUF = 4,
+ ENET_SOCKOPT_REUSEADDR = 5,
+ ENET_SOCKOPT_RCVTIMEO = 6,
+ ENET_SOCKOPT_SNDTIMEO = 7,
+ ENET_SOCKOPT_ERROR = 8,
+ ENET_SOCKOPT_NODELAY = 9
+} ENetSocketOption;
+
+typedef enum _ENetSocketShutdown
+{
+ ENET_SOCKET_SHUTDOWN_READ = 0,
+ ENET_SOCKET_SHUTDOWN_WRITE = 1,
+ ENET_SOCKET_SHUTDOWN_READ_WRITE = 2
+} ENetSocketShutdown;
+
+#define ENET_HOST_ANY 0
+#define ENET_HOST_BROADCAST 0xFFFFFFFFU
+#define ENET_PORT_ANY 0
+
+/**
+ * Portable internet address structure.
+ *
+ * The host must be specified in network byte-order, and the port must be in host
+ * byte-order. The constant ENET_HOST_ANY may be used to specify the default
+ * server host. The constant ENET_HOST_BROADCAST may be used to specify the
+ * broadcast address (255.255.255.255). This makes sense for enet_host_connect,
+ * but not for enet_host_create. Once a server responds to a broadcast, the
+ * address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
+ */
+typedef struct _ENetAddress
+{
+ enet_uint32 host;
+ enet_uint16 port;
+} ENetAddress;
+
+/**
+ * Packet flag bit constants.
+ *
+ * The host must be specified in network byte-order, and the port must be in
+ * host byte-order. The constant ENET_HOST_ANY may be used to specify the
+ * default server host.
+
+ @sa ENetPacket
+*/
+typedef enum _ENetPacketFlag
+{
+ /** packet must be received by the target peer and resend attempts should be
+ * made until the packet is delivered */
+ ENET_PACKET_FLAG_RELIABLE = (1 << 0),
+ /** packet will not be sequenced with other packets
+ * not supported for reliable packets
+ */
+ ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1),
+ /** packet will not allocate data, and user must supply it instead */
+ ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2),
+ /** packet will be fragmented using unreliable (instead of reliable) sends
+ * if it exceeds the MTU */
+ ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3),
+
+ /** whether the packet has been sent from all queues it has been entered into */
+ ENET_PACKET_FLAG_SENT = (1<<8)
+} ENetPacketFlag;
+
+typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
+
+/**
+ * ENet packet structure.
+ *
+ * An ENet data packet that may be sent to or received from a peer. The shown
+ * fields should only be read and never modified. The data field contains the
+ * allocated data for the packet. The dataLength fields specifies the length
+ * of the allocated data. The flags field is either 0 (specifying no flags),
+ * or a bitwise-or of any combination of the following flags:
+ *
+ * ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer
+ * and resend attempts should be made until the packet is delivered
+ *
+ * ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets
+ * (not supported for reliable packets)
+ *
+ * ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead
+
+ @sa ENetPacketFlag
+ */
+typedef struct _ENetPacket
+{
+ size_t referenceCount; /**< internal use only */
+ enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */
+ enet_uint8 * data; /**< allocated data for packet */
+ size_t dataLength; /**< length of data */
+ ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */
+ void * userData; /**< application private data, may be freely modified */
+} ENetPacket;
+
+typedef struct _ENetAcknowledgement
+{
+ ENetListNode acknowledgementList;
+ enet_uint32 sentTime;
+ ENetProtocol command;
+} ENetAcknowledgement;
+
+typedef struct _ENetOutgoingCommand
+{
+ ENetListNode outgoingCommandList;
+ enet_uint16 reliableSequenceNumber;
+ enet_uint16 unreliableSequenceNumber;
+ enet_uint32 sentTime;
+ enet_uint32 roundTripTimeout;
+ enet_uint32 roundTripTimeoutLimit;
+ enet_uint32 fragmentOffset;
+ enet_uint16 fragmentLength;
+ enet_uint16 sendAttempts;
+ ENetProtocol command;
+ ENetPacket * packet;
+} ENetOutgoingCommand;
+
+typedef struct _ENetIncomingCommand
+{
+ ENetListNode incomingCommandList;
+ enet_uint16 reliableSequenceNumber;
+ enet_uint16 unreliableSequenceNumber;
+ ENetProtocol command;
+ enet_uint32 fragmentCount;
+ enet_uint32 fragmentsRemaining;
+ enet_uint32 * fragments;
+ ENetPacket * packet;
+} ENetIncomingCommand;
+
+typedef enum _ENetPeerState
+{
+ ENET_PEER_STATE_DISCONNECTED = 0,
+ ENET_PEER_STATE_CONNECTING = 1,
+ ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2,
+ ENET_PEER_STATE_CONNECTION_PENDING = 3,
+ ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4,
+ ENET_PEER_STATE_CONNECTED = 5,
+ ENET_PEER_STATE_DISCONNECT_LATER = 6,
+ ENET_PEER_STATE_DISCONNECTING = 7,
+ ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8,
+ ENET_PEER_STATE_ZOMBIE = 9
+} ENetPeerState;
+
+#ifndef ENET_BUFFER_MAXIMUM
+#define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS)
+#endif
+
+enum
+{
+ ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
+ ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024,
+ ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000,
+ ENET_HOST_DEFAULT_MTU = 1400,
+ ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024,
+ ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024,
+
+ ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500,
+ ENET_PEER_DEFAULT_PACKET_THROTTLE = 32,
+ ENET_PEER_PACKET_THROTTLE_SCALE = 32,
+ ENET_PEER_PACKET_THROTTLE_COUNTER = 7,
+ ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2,
+ ENET_PEER_PACKET_THROTTLE_DECELERATION = 2,
+ ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000,
+ ENET_PEER_PACKET_LOSS_SCALE = (1 << 16),
+ ENET_PEER_PACKET_LOSS_INTERVAL = 10000,
+ ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024,
+ ENET_PEER_TIMEOUT_LIMIT = 32,
+ ENET_PEER_TIMEOUT_MINIMUM = 5000,
+ ENET_PEER_TIMEOUT_MAXIMUM = 30000,
+ ENET_PEER_PING_INTERVAL = 500,
+ ENET_PEER_UNSEQUENCED_WINDOWS = 64,
+ ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024,
+ ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32,
+ ENET_PEER_RELIABLE_WINDOWS = 16,
+ ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000,
+ ENET_PEER_FREE_RELIABLE_WINDOWS = 8
+};
+
+typedef struct _ENetChannel
+{
+ enet_uint16 outgoingReliableSequenceNumber;
+ enet_uint16 outgoingUnreliableSequenceNumber;
+ enet_uint16 usedReliableWindows;
+ enet_uint16 reliableWindows [ENET_PEER_RELIABLE_WINDOWS];
+ enet_uint16 incomingReliableSequenceNumber;
+ enet_uint16 incomingUnreliableSequenceNumber;
+ ENetList incomingReliableCommands;
+ ENetList incomingUnreliableCommands;
+} ENetChannel;
+
+/**
+ * An ENet peer which data packets may be sent or received from.
+ *
+ * No fields should be modified unless otherwise specified.
+ */
+typedef struct _ENetPeer
+{
+ ENetListNode dispatchList;
+ struct _ENetHost * host;
+ enet_uint16 outgoingPeerID;
+ enet_uint16 incomingPeerID;
+ enet_uint32 connectID;
+ enet_uint8 outgoingSessionID;
+ enet_uint8 incomingSessionID;
+ ENetAddress address; /**< Internet address of the peer */
+ void * data; /**< Application private data, may be freely modified */
+ ENetPeerState state;
+ ENetChannel * channels;
+ size_t channelCount; /**< Number of channels allocated for communication with peer */
+ enet_uint32 incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */
+ enet_uint32 outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */
+ enet_uint32 incomingBandwidthThrottleEpoch;
+ enet_uint32 outgoingBandwidthThrottleEpoch;
+ enet_uint32 incomingDataTotal;
+ enet_uint32 outgoingDataTotal;
+ enet_uint32 lastSendTime;
+ enet_uint32 lastReceiveTime;
+ enet_uint32 nextTimeout;
+ enet_uint32 earliestTimeout;
+ enet_uint32 packetLossEpoch;
+ enet_uint32 packetsSent;
+ enet_uint32 packetsLost;
+ enet_uint32 packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */
+ enet_uint32 packetLossVariance;
+ enet_uint32 packetThrottle;
+ enet_uint32 packetThrottleLimit;
+ enet_uint32 packetThrottleCounter;
+ enet_uint32 packetThrottleEpoch;
+ enet_uint32 packetThrottleAcceleration;
+ enet_uint32 packetThrottleDeceleration;
+ enet_uint32 packetThrottleInterval;
+ enet_uint32 pingInterval;
+ enet_uint32 timeoutLimit;
+ enet_uint32 timeoutMinimum;
+ enet_uint32 timeoutMaximum;
+ enet_uint32 lastRoundTripTime;
+ enet_uint32 lowestRoundTripTime;
+ enet_uint32 lastRoundTripTimeVariance;
+ enet_uint32 highestRoundTripTimeVariance;
+ enet_uint32 roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */
+ enet_uint32 roundTripTimeVariance;
+ enet_uint32 mtu;
+ enet_uint32 windowSize;
+ enet_uint32 reliableDataInTransit;
+ enet_uint16 outgoingReliableSequenceNumber;
+ ENetList acknowledgements;
+ ENetList sentReliableCommands;
+ ENetList sentUnreliableCommands;
+ ENetList outgoingReliableCommands;
+ ENetList outgoingUnreliableCommands;
+ ENetList dispatchedCommands;
+ int needsDispatch;
+ enet_uint16 incomingUnsequencedGroup;
+ enet_uint16 outgoingUnsequencedGroup;
+ enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
+ enet_uint32 eventData;
+ size_t totalWaitingData;
+} ENetPeer;
+
+/** An ENet packet compressor for compressing UDP packets before socket sends or receives.
+ */
+typedef struct _ENetCompressor
+{
+ /** Context data for the compressor. Must be non-NULL. */
+ void * context;
+ /** Compresses from inBuffers[0:inBufferCount-1], containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
+ size_t (ENET_CALLBACK * compress) (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit);
+ /** Decompresses from inData, containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
+ size_t (ENET_CALLBACK * decompress) (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit);
+ /** Destroys the context when compression is disabled or the host is destroyed. May be NULL. */
+ void (ENET_CALLBACK * destroy) (void * context);
+} ENetCompressor;
+
+/** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */
+typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * buffers, size_t bufferCount);
+
+/** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */
+typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, struct _ENetEvent * event);
+
+/** An ENet host for communicating with peers.
+ *
+ * No fields should be modified unless otherwise stated.
+
+ @sa enet_host_create()
+ @sa enet_host_destroy()
+ @sa enet_host_connect()
+ @sa enet_host_service()
+ @sa enet_host_flush()
+ @sa enet_host_broadcast()
+ @sa enet_host_compress()
+ @sa enet_host_compress_with_range_coder()
+ @sa enet_host_channel_limit()
+ @sa enet_host_bandwidth_limit()
+ @sa enet_host_bandwidth_throttle()
+ */
+typedef struct _ENetHost
+{
+ ENetSocket socket;
+ ENetAddress address; /**< Internet address of the host */
+ enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */
+ enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */
+ enet_uint32 bandwidthThrottleEpoch;
+ enet_uint32 mtu;
+ enet_uint32 randomSeed;
+ int recalculateBandwidthLimits;
+ ENetPeer * peers; /**< array of peers allocated for this host */
+ size_t peerCount; /**< number of peers allocated for this host */
+ size_t channelLimit; /**< maximum number of channels allowed for connected peers */
+ enet_uint32 serviceTime;
+ ENetList dispatchQueue;
+ int continueSending;
+ size_t packetSize;
+ enet_uint16 headerFlags;
+ ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
+ size_t commandCount;
+ ENetBuffer buffers [ENET_BUFFER_MAXIMUM];
+ size_t bufferCount;
+ ENetChecksumCallback checksum; /**< callback the user can set to enable packet checksums for this host */
+ ENetCompressor compressor;
+ enet_uint8 packetData [2][ENET_PROTOCOL_MAXIMUM_MTU];
+ ENetAddress receivedAddress;
+ enet_uint8 * receivedData;
+ size_t receivedDataLength;
+ enet_uint32 totalSentData; /**< total data sent, user should reset to 0 as needed to prevent overflow */
+ enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */
+ enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */
+ enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */
+ ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */
+ size_t connectedPeers;
+ size_t bandwidthLimitedPeers;
+ size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */
+ size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */
+ size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */
+} ENetHost;
+
+/**
+ * An ENet event type, as specified in @ref ENetEvent.
+ */
+typedef enum _ENetEventType
+{
+ /** no event occurred within the specified time limit */
+ ENET_EVENT_TYPE_NONE = 0,
+
+ /** a connection request initiated by enet_host_connect has completed.
+ * The peer field contains the peer which successfully connected.
+ */
+ ENET_EVENT_TYPE_CONNECT = 1,
+
+ /** a peer has disconnected. This event is generated on a successful
+ * completion of a disconnect initiated by enet_pper_disconnect, if
+ * a peer has timed out, or if a connection request intialized by
+ * enet_host_connect has timed out. The peer field contains the peer
+ * which disconnected. The data field contains user supplied data
+ * describing the disconnection, or 0, if none is available.
+ */
+ ENET_EVENT_TYPE_DISCONNECT = 2,
+
+ /** a packet has been received from a peer. The peer field specifies the
+ * peer which sent the packet. The channelID field specifies the channel
+ * number upon which the packet was received. The packet field contains
+ * the packet that was received; this packet must be destroyed with
+ * enet_packet_destroy after use.
+ */
+ ENET_EVENT_TYPE_RECEIVE = 3
+} ENetEventType;
+
+/**
+ * An ENet event as returned by enet_host_service().
+
+ @sa enet_host_service
+ */
+typedef struct _ENetEvent
+{
+ ENetEventType type; /**< type of the event */
+ ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */
+ enet_uint8 channelID; /**< channel on the peer that generated the event, if appropriate */
+ enet_uint32 data; /**< data associated with the event, if appropriate */
+ ENetPacket * packet; /**< packet associated with the event, if appropriate */
+} ENetEvent;
+
+/** @defgroup global ENet global functions
+ @{
+*/
+
+/**
+ Initializes ENet globally. Must be called prior to using any functions in
+ ENet.
+ @returns 0 on success, < 0 on failure
+*/
+ENET_API int enet_initialize (void);
+
+/**
+ Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored.
+
+ @param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use
+ @param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults
+ @returns 0 on success, < 0 on failure
+*/
+ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits);
+
+/**
+ Shuts down ENet globally. Should be called when a program that has
+ initialized ENet exits.
+*/
+ENET_API void enet_deinitialize (void);
+
+/**
+ Gives the linked version of the ENet library.
+ @returns the version number
+*/
+ENET_API ENetVersion enet_linked_version (void);
+
+/** @} */
+
+/** @defgroup private ENet private implementation functions */
+
+/**
+ Returns the wall-time in milliseconds. Its initial value is unspecified
+ unless otherwise set.
+ */
+ENET_API enet_uint32 enet_time_get (void);
+/**
+ Sets the current wall-time in milliseconds.
+ */
+ENET_API void enet_time_set (enet_uint32);
+
+/** @defgroup socket ENet socket functions
+ @{
+*/
+ENET_API ENetSocket enet_socket_create (ENetSocketType);
+ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *);
+ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *);
+ENET_API int enet_socket_listen (ENetSocket, int);
+ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *);
+ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *);
+ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t);
+ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t);
+ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32);
+ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int);
+ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *);
+ENET_API int enet_socket_shutdown (ENetSocket, ENetSocketShutdown);
+ENET_API void enet_socket_destroy (ENetSocket);
+ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32);
+
+/** @} */
+
+/** @defgroup Address ENet address functions
+ @{
+*/
+/** Attempts to resolve the host named by the parameter hostName and sets
+ the host field in the address parameter if successful.
+ @param address destination to store resolved address
+ @param hostName host name to lookup
+ @retval 0 on success
+ @retval < 0 on failure
+ @returns the address of the given hostName in address on success
+*/
+ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
+
+/** Gives the printable form of the IP address specified in the address parameter.
+ @param address address printed
+ @param hostName destination for name, must not be NULL
+ @param nameLength maximum length of hostName.
+ @returns the null-terminated name of the host in hostName on success
+ @retval 0 on success
+ @retval < 0 on failure
+*/
+ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength);
+
+/** Attempts to do a reverse lookup of the host field in the address parameter.
+ @param address address used for reverse lookup
+ @param hostName destination for name, must not be NULL
+ @param nameLength maximum length of hostName.
+ @returns the null-terminated name of the host in hostName on success
+ @retval 0 on success
+ @retval < 0 on failure
+*/
+ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength);
+
+/** @} */
+
+ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32);
+ENET_API void enet_packet_destroy (ENetPacket *);
+ENET_API int enet_packet_resize (ENetPacket *, size_t);
+ENET_API enet_uint32 enet_crc32 (const ENetBuffer *, size_t);
+
+ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
+ENET_API void enet_host_destroy (ENetHost *);
+ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32);
+ENET_API int enet_host_check_events (ENetHost *, ENetEvent *);
+ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32);
+ENET_API void enet_host_flush (ENetHost *);
+ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *);
+ENET_API void enet_host_compress (ENetHost *, const ENetCompressor *);
+ENET_API int enet_host_compress_with_range_coder (ENetHost * host);
+ENET_API void enet_host_channel_limit (ENetHost *, size_t);
+ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
+extern void enet_host_bandwidth_throttle (ENetHost *);
+extern enet_uint32 enet_host_random_seed (void);
+
+ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
+ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
+ENET_API void enet_peer_ping (ENetPeer *);
+ENET_API void enet_peer_ping_interval (ENetPeer *, enet_uint32);
+ENET_API void enet_peer_timeout (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
+ENET_API void enet_peer_reset (ENetPeer *);
+ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32);
+ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32);
+ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32);
+ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
+extern int enet_peer_throttle (ENetPeer *, enet_uint32);
+extern void enet_peer_reset_queues (ENetPeer *);
+extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *);
+extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16);
+extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32);
+extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16);
+extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *);
+extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *);
+extern void enet_peer_on_connect (ENetPeer *);
+extern void enet_peer_on_disconnect (ENetPeer *);
+
+ENET_API void * enet_range_coder_create (void);
+ENET_API void enet_range_coder_destroy (void *);
+ENET_API size_t enet_range_coder_compress (void *, const ENetBuffer *, size_t, size_t, enet_uint8 *, size_t);
+ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, enet_uint8 *, size_t);
+
+extern size_t enet_protocol_command_size (enet_uint8);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ENET_ENET_H__ */
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/list.h b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/list.h
new file mode 100644
index 0000000000..d7b2600848
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/list.h
@@ -0,0 +1,43 @@
+/**
+ @file list.h
+ @brief ENet list management
+*/
+#ifndef __ENET_LIST_H__
+#define __ENET_LIST_H__
+
+#include <stdlib.h>
+
+typedef struct _ENetListNode
+{
+ struct _ENetListNode * next;
+ struct _ENetListNode * previous;
+} ENetListNode;
+
+typedef ENetListNode * ENetListIterator;
+
+typedef struct _ENetList
+{
+ ENetListNode sentinel;
+} ENetList;
+
+extern void enet_list_clear (ENetList *);
+
+extern ENetListIterator enet_list_insert (ENetListIterator, void *);
+extern void * enet_list_remove (ENetListIterator);
+extern ENetListIterator enet_list_move (ENetListIterator, void *, void *);
+
+extern size_t enet_list_size (ENetList *);
+
+#define enet_list_begin(list) ((list) -> sentinel.next)
+#define enet_list_end(list) (& (list) -> sentinel)
+
+#define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list))
+
+#define enet_list_next(iterator) ((iterator) -> next)
+#define enet_list_previous(iterator) ((iterator) -> previous)
+
+#define enet_list_front(list) ((void *) (list) -> sentinel.next)
+#define enet_list_back(list) ((void *) (list) -> sentinel.previous)
+
+#endif /* __ENET_LIST_H__ */
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/protocol.h b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/protocol.h
new file mode 100644
index 0000000000..5a2970e188
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/protocol.h
@@ -0,0 +1,198 @@
+/**
+ @file protocol.h
+ @brief ENet protocol
+*/
+#ifndef __ENET_PROTOCOL_H__
+#define __ENET_PROTOCOL_H__
+
+#include "types.h"
+
+enum
+{
+ ENET_PROTOCOL_MINIMUM_MTU = 576,
+ ENET_PROTOCOL_MAXIMUM_MTU = 4096,
+ ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32,
+ ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096,
+ ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536,
+ ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1,
+ ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255,
+ ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF,
+ ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024
+};
+
+typedef enum _ENetProtocolCommand
+{
+ ENET_PROTOCOL_COMMAND_NONE = 0,
+ ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1,
+ ENET_PROTOCOL_COMMAND_CONNECT = 2,
+ ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3,
+ ENET_PROTOCOL_COMMAND_DISCONNECT = 4,
+ ENET_PROTOCOL_COMMAND_PING = 5,
+ ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6,
+ ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7,
+ ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8,
+ ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9,
+ ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10,
+ ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11,
+ ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12,
+ ENET_PROTOCOL_COMMAND_COUNT = 13,
+
+ ENET_PROTOCOL_COMMAND_MASK = 0x0F
+} ENetProtocolCommand;
+
+typedef enum _ENetProtocolFlag
+{
+ ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7),
+ ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6),
+
+ ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14),
+ ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15),
+ ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME,
+
+ ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12),
+ ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12
+} ENetProtocolFlag;
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#define ENET_PACKED
+#elif defined(__GNUC__) || defined(__clang__)
+#define ENET_PACKED __attribute__ ((packed))
+#else
+#define ENET_PACKED
+#endif
+
+typedef struct _ENetProtocolHeader
+{
+ enet_uint16 peerID;
+ enet_uint16 sentTime;
+} ENET_PACKED ENetProtocolHeader;
+
+typedef struct _ENetProtocolCommandHeader
+{
+ enet_uint8 command;
+ enet_uint8 channelID;
+ enet_uint16 reliableSequenceNumber;
+} ENET_PACKED ENetProtocolCommandHeader;
+
+typedef struct _ENetProtocolAcknowledge
+{
+ ENetProtocolCommandHeader header;
+ enet_uint16 receivedReliableSequenceNumber;
+ enet_uint16 receivedSentTime;
+} ENET_PACKED ENetProtocolAcknowledge;
+
+typedef struct _ENetProtocolConnect
+{
+ ENetProtocolCommandHeader header;
+ enet_uint16 outgoingPeerID;
+ enet_uint8 incomingSessionID;
+ enet_uint8 outgoingSessionID;
+ enet_uint32 mtu;
+ enet_uint32 windowSize;
+ enet_uint32 channelCount;
+ enet_uint32 incomingBandwidth;
+ enet_uint32 outgoingBandwidth;
+ enet_uint32 packetThrottleInterval;
+ enet_uint32 packetThrottleAcceleration;
+ enet_uint32 packetThrottleDeceleration;
+ enet_uint32 connectID;
+ enet_uint32 data;
+} ENET_PACKED ENetProtocolConnect;
+
+typedef struct _ENetProtocolVerifyConnect
+{
+ ENetProtocolCommandHeader header;
+ enet_uint16 outgoingPeerID;
+ enet_uint8 incomingSessionID;
+ enet_uint8 outgoingSessionID;
+ enet_uint32 mtu;
+ enet_uint32 windowSize;
+ enet_uint32 channelCount;
+ enet_uint32 incomingBandwidth;
+ enet_uint32 outgoingBandwidth;
+ enet_uint32 packetThrottleInterval;
+ enet_uint32 packetThrottleAcceleration;
+ enet_uint32 packetThrottleDeceleration;
+ enet_uint32 connectID;
+} ENET_PACKED ENetProtocolVerifyConnect;
+
+typedef struct _ENetProtocolBandwidthLimit
+{
+ ENetProtocolCommandHeader header;
+ enet_uint32 incomingBandwidth;
+ enet_uint32 outgoingBandwidth;
+} ENET_PACKED ENetProtocolBandwidthLimit;
+
+typedef struct _ENetProtocolThrottleConfigure
+{
+ ENetProtocolCommandHeader header;
+ enet_uint32 packetThrottleInterval;
+ enet_uint32 packetThrottleAcceleration;
+ enet_uint32 packetThrottleDeceleration;
+} ENET_PACKED ENetProtocolThrottleConfigure;
+
+typedef struct _ENetProtocolDisconnect
+{
+ ENetProtocolCommandHeader header;
+ enet_uint32 data;
+} ENET_PACKED ENetProtocolDisconnect;
+
+typedef struct _ENetProtocolPing
+{
+ ENetProtocolCommandHeader header;
+} ENET_PACKED ENetProtocolPing;
+
+typedef struct _ENetProtocolSendReliable
+{
+ ENetProtocolCommandHeader header;
+ enet_uint16 dataLength;
+} ENET_PACKED ENetProtocolSendReliable;
+
+typedef struct _ENetProtocolSendUnreliable
+{
+ ENetProtocolCommandHeader header;
+ enet_uint16 unreliableSequenceNumber;
+ enet_uint16 dataLength;
+} ENET_PACKED ENetProtocolSendUnreliable;
+
+typedef struct _ENetProtocolSendUnsequenced
+{
+ ENetProtocolCommandHeader header;
+ enet_uint16 unsequencedGroup;
+ enet_uint16 dataLength;
+} ENET_PACKED ENetProtocolSendUnsequenced;
+
+typedef struct _ENetProtocolSendFragment
+{
+ ENetProtocolCommandHeader header;
+ enet_uint16 startSequenceNumber;
+ enet_uint16 dataLength;
+ enet_uint32 fragmentCount;
+ enet_uint32 fragmentNumber;
+ enet_uint32 totalLength;
+ enet_uint32 fragmentOffset;
+} ENET_PACKED ENetProtocolSendFragment;
+
+typedef union _ENetProtocol
+{
+ ENetProtocolCommandHeader header;
+ ENetProtocolAcknowledge acknowledge;
+ ENetProtocolConnect connect;
+ ENetProtocolVerifyConnect verifyConnect;
+ ENetProtocolDisconnect disconnect;
+ ENetProtocolPing ping;
+ ENetProtocolSendReliable sendReliable;
+ ENetProtocolSendUnreliable sendUnreliable;
+ ENetProtocolSendUnsequenced sendUnsequenced;
+ ENetProtocolSendFragment sendFragment;
+ ENetProtocolBandwidthLimit bandwidthLimit;
+ ENetProtocolThrottleConfigure throttleConfigure;
+} ENET_PACKED ENetProtocol;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif
+
+#endif /* __ENET_PROTOCOL_H__ */
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/time.h b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/time.h
new file mode 100644
index 0000000000..c82a546035
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/time.h
@@ -0,0 +1,18 @@
+/**
+ @file time.h
+ @brief ENet time constants and macros
+*/
+#ifndef __ENET_TIME_H__
+#define __ENET_TIME_H__
+
+#define ENET_TIME_OVERFLOW 86400000
+
+#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW)
+#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW)
+#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b))
+#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b))
+
+#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b))
+
+#endif /* __ENET_TIME_H__ */
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/types.h b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/types.h
new file mode 100644
index 0000000000..ab010a4b13
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/types.h
@@ -0,0 +1,13 @@
+/**
+ @file types.h
+ @brief type definitions for ENet
+*/
+#ifndef __ENET_TYPES_H__
+#define __ENET_TYPES_H__
+
+typedef unsigned char enet_uint8; /**< unsigned 8-bit type */
+typedef unsigned short enet_uint16; /**< unsigned 16-bit type */
+typedef unsigned int enet_uint32; /**< unsigned 32-bit type */
+
+#endif /* __ENET_TYPES_H__ */
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/unix.h b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/unix.h
new file mode 100644
index 0000000000..f4d1f8776c
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/unix.h
@@ -0,0 +1,40 @@
+/**
+ @file unix.h
+ @brief ENet Unix header
+*/
+#ifndef __ENET_UNIX_H__
+#define __ENET_UNIX_H__
+
+#ifdef MSG_MAXIOVLEN
+#define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN
+#endif
+
+typedef int ENetSocket;
+
+#define ENET_SOCKET_NULL -1
+
+#define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */
+#define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */
+
+#define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */
+#define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */
+
+typedef struct
+{
+ void * data;
+ size_t dataLength;
+} ENetBuffer;
+
+#define ENET_CALLBACK
+
+#define ENET_API extern
+
+typedef int ENetSocketSet;
+
+#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset))
+#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset))
+#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset))
+#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset))
+
+#endif /* __ENET_UNIX_H__ */
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/utility.h b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/utility.h
new file mode 100644
index 0000000000..e48a476be3
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/utility.h
@@ -0,0 +1,12 @@
+/**
+ @file utility.h
+ @brief ENet utility header
+*/
+#ifndef __ENET_UTILITY_H__
+#define __ENET_UTILITY_H__
+
+#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#endif /* __ENET_UTILITY_H__ */
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/win32.h b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/win32.h
new file mode 100644
index 0000000000..e73ca9d052
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/enet/include/win32.h
@@ -0,0 +1,57 @@
+/**
+ @file win32.h
+ @brief ENet Win32 header
+*/
+#ifndef __ENET_WIN32_H__
+#define __ENET_WIN32_H__
+
+#ifdef _MSC_VER
+#ifdef ENET_BUILDING_LIB
+#pragma warning (disable: 4267) // size_t to int conversion
+#pragma warning (disable: 4244) // 64bit to 32bit int
+#pragma warning (disable: 4018) // signed/unsigned mismatch
+#pragma warning (disable: 4146) // unary minus operator applied to unsigned type
+#endif
+#endif
+
+#include <stdlib.h>
+#include <winsock2.h>
+
+typedef SOCKET ENetSocket;
+
+#define ENET_SOCKET_NULL INVALID_SOCKET
+
+#define ENET_HOST_TO_NET_16(value) (htons (value))
+#define ENET_HOST_TO_NET_32(value) (htonl (value))
+
+#define ENET_NET_TO_HOST_16(value) (ntohs (value))
+#define ENET_NET_TO_HOST_32(value) (ntohl (value))
+
+typedef struct
+{
+ size_t dataLength;
+ void * data;
+} ENetBuffer;
+
+#define ENET_CALLBACK __cdecl
+
+#ifdef ENET_DLL
+#ifdef ENET_BUILDING_LIB
+#define ENET_API __declspec( dllexport )
+#else
+#define ENET_API __declspec( dllimport )
+#endif /* ENET_BUILDING_LIB */
+#else /* !ENET_DLL */
+#define ENET_API extern
+#endif /* ENET_DLL */
+
+typedef fd_set ENetSocketSet;
+
+#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset))
+#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset))
+#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset))
+#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset))
+
+#endif /* __ENET_WIN32_H__ */
+
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/engine.c b/apps/plugins/sdl/progs/duke3d/Engine/src/engine.c
new file mode 100644
index 0000000000..c0a7390882
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/engine.c
@@ -0,0 +1,9349 @@
+/*
+ * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * See the included license file "BUILDLIC.TXT" for license info.
+ * This file has been modified from Ken Silverman's original release
+ */
+
+/* SUPERBUILD define is in engine.h ... */
+
+#define ENGINE
+
+#include "platform.h"
+
+#include "build.h"
+
+#include "engine.h"
+#include "tiles.h"
+
+int32_t stereowidth = 23040, stereopixelwidth = 28, ostereopixelwidth = -1;
+int32_t stereomode = 0, visualpage, activepage, whiteband, blackband;
+uint8_t oa1, o3c2, ortca, ortcb, overtbits, laststereoint;
+
+#include "display.h"
+
+#define MAXCLIPNUM 512
+#define MAXPERMS 512
+#define MAXTILEFILES 256
+#define MAXYSAVES ((MAXXDIM*MAXSPRITES)>>7)
+#define MAXNODESPERLINE 42 /* Warning: This depends on MAXYSAVES & MAXYDIM! */
+#define MAXWALLSB 2048
+#define MAXCLIPDIST 1024
+
+/* used to be static. --ryan. */
+uint8_t moustat = 0;
+
+int32_t transarea = 0, beforedrawrooms = 1;
+
+/* used to be static. --ryan. */
+int32_t oxdimen = -1, oviewingrange = -1, oxyaspect = -1;
+
+/* used to be static. --ryan. */
+int32_t curbrightness = 0;
+
+/* Textured Map variables */
+static uint8_t globalpolytype;
+static short *dotp1[MAXYDIM], *dotp2[MAXYDIM];
+
+static char tempbuf[MAXWALLS];
+
+int32_t ebpbak, espbak;
+int32_t slopalookup[16384];
+
+/*
+ * !!! used to be static. If we ever put the original setgamemode() back, this
+ * !!! can be made static again. --ryan.
+ */
+uint8_t permanentlock = 255;
+int32_t mapversion;
+
+uint8_t picsiz[MAXTILES], tilefilenum[MAXTILES];
+int32_t lastageclock;
+int32_t tilefileoffs[MAXTILES];
+
+int32_t artsize = 0, cachesize = 0;
+
+static short radarang[1280], radarang2[MAXXDIM+1];
+static uint16_t sqrtable[4096], shlookup[4096+256];
+uint8_t pow2char[8] = {1,2,4,8,16,32,64,-128};
+int32_t pow2long[32] =
+{
+ 1L,2L,4L,8L,
+ 16L,32L,64L,128L,
+ 256L,512L,1024L,2048L,
+ 4096L,8192L,16384L,32768L,
+ 65536L,131072L,262144L,524288L,
+ 1048576L,2097152L,4194304L,8388608L,
+ 16777216L,33554432L,67108864L,134217728L,
+ 268435456L,536870912L,1073741824L,2147483647L,
+};
+int32_t reciptable[2048], fpuasm;
+
+char kensmessage[128];
+
+uint8_t britable[16][64];
+uint8_t textfont[1024], smalltextfont[1024];
+
+
+
+
+
+
+
+
+
+enum vector_index_e {VEC_X=0,VEC_Y=1};
+enum screenSpaceCoo_index_e {VEC_COL=0,VEC_DIST=1};
+typedef int32_t vector_t[2];
+typedef int32_t coo2D_t[2];
+// This is the structure emitted for each wall that is potentially visible.
+// A stack of those is populated when the sectors are scanned.
+typedef struct pvWall_s{
+ vector_t cameraSpaceCoo[2]; //Camera space coordinates of the wall endpoints. Access with vector_index_e.
+ int16_t sectorId; //The index of the sector this wall belongs to in the map database.
+ int16_t worldWallId; //The index of the wall in the map database.
+ coo2D_t screenSpaceCoo[2]; //Screen space coordinate of the wall endpoints. Access with screenSpaceCoo_index_e.
+} pvWall_t;
+
+// Potentially Visible walls are stored in this stack.
+pvWall_t pvWalls[MAXWALLSB];
+
+
+
+
+//xb1 and xb2 seems to be storing the column of the wall endpoint
+//yb1 and yb2 store the Y distance from the camera.
+
+//static int32_t xb1[MAXWALLSB], yb1[MAXWALLSB], xb2[MAXWALLSB], yb2[MAXWALLSB];
+
+/*
+//rx1,rx2,ry1,ry2 stores the cameraspace wall endpoints coordinates.
+static int32_t rx1[MAXWALLSB], ry1[MAXWALLSB], rx2[MAXWALLSB], ry2[MAXWALLSB];
+static short thesector[MAXWALLSB], thewall[MAXWALLSB];
+*/
+
+// bunchWallsList contains the list of walls in a bunch.
+static short bunchWallsList[MAXWALLSB];
+
+static short bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
+
+
+
+
+
+
+
+static short smost[MAXYSAVES], smostcnt;
+static short smoststart[MAXWALLSB];
+static uint8_t smostwalltype[MAXWALLSB];
+static int32_t smostwall[MAXWALLSB], smostwallcnt = -1L;
+
+static short maskwall[MAXWALLSB], maskwallcnt;
+static int32_t spritesx[MAXSPRITESONSCREEN];
+static int32_t spritesy[MAXSPRITESONSCREEN+1];
+static int32_t spritesz[MAXSPRITESONSCREEN];
+static spritetype *tspriteptr[MAXSPRITESONSCREEN];
+
+//FCS: (up-most pixel on column x that can still be drawn to)
+short umost[MAXXDIM+1];
+
+//FCS: (down-most pixel +1 on column x that can still be drawn to)
+short dmost[MAXXDIM+1];
+
+int16_t bakumost[MAXXDIM+1], bakdmost[MAXXDIM+1];
+short uplc[MAXXDIM+1], dplc[MAXXDIM+1];
+static int16_t uwall[MAXXDIM+1], dwall[MAXXDIM+1];
+static int32_t swplc[MAXXDIM+1], lplc[MAXXDIM+1];
+static int32_t swall[MAXXDIM+1], lwall[MAXXDIM+4];
+int32_t xdimen = -1, xdimenrecip, halfxdimen, xdimenscale, xdimscale;
+int32_t wx1, wy1, wx2, wy2, ydimen;
+int32_t viewoffset;
+
+static int32_t rxi[8], ryi[8], rzi[8], rxi2[8], ryi2[8], rzi2[8];
+static int32_t xsi[8], ysi[8];
+
+/* used to be static. --ryan. */
+int32_t *horizlookup=0, *horizlookup2=0, horizycent;
+
+int32_t globalposx, globalposy, globalposz, globalhoriz;
+int16_t globalang, globalcursectnum;
+int32_t globalpal, cosglobalang, singlobalang;
+int32_t cosviewingrangeglobalang, sinviewingrangeglobalang;
+uint8_t *globalpalwritten;
+int32_t globaluclip, globaldclip, globvis = 0;
+int32_t globalvisibility, globalhisibility, globalpisibility, globalcisibility;
+uint8_t globparaceilclip, globparaflorclip;
+
+int32_t xyaspect, viewingrangerecip;
+
+int32_t asm1, asm4;
+intptr_t asm2, asm3;
+
+
+int32_t vplce[4], vince[4];
+intptr_t bufplce[4];
+
+uint8_t* palookupoffse[4];
+
+uint8_t globalxshift, globalyshift;
+int32_t globalxpanning, globalypanning, globalshade;
+int16_t globalpicnum, globalshiftval;
+int32_t globalzd, globalyscale, globalorientation;
+uint8_t* globalbufplc;
+int32_t globalx1, globaly1, globalx2, globaly2, globalx3, globaly3, globalzx;
+int32_t globalx, globaly, globalz;
+
+//FCS:
+// Those two variables are using during portal flooding:
+// sectorBorder is the stack and sectorbordercnt is the stack counter.
+// There is no really point to have this on the heap. That would have been better on the stack.
+
+//static short sectorborder[256], sectorbordercnt;
+//FCS: Moved this on the stack
+
+static uint8_t tablesloaded = 0;
+int32_t pageoffset, ydim16, qsetmode = 0;
+int32_t startposx, startposy, startposz;
+int16_t startang, startsectnum;
+int16_t pointhighlight, linehighlight, highlightcnt;
+static int32_t lastx[MAXYDIM];
+uint8_t paletteloaded = 0;
+
+#define FASTPALGRIDSIZ 8
+static int32_t rdist[129], gdist[129], bdist[129];
+static uint8_t colhere[((FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2))>>3];
+static uint8_t colhead[(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)*(FASTPALGRIDSIZ+2)];
+static int32_t colnext[256];
+static uint8_t coldist[8] = {0,1,2,3,4,3,2,1};
+static int32_t colscan[27];
+
+static int16_t clipnum, hitwalls[4];
+int32_t hitscangoalx = (1<<29)-1, hitscangoaly = (1<<29)-1;
+
+typedef struct {
+ int32_t x1, y1, x2, y2;
+} linetype;
+static linetype clipit[MAXCLIPNUM];
+static short clipsectorlist[MAXCLIPNUM], clipsectnum;
+static short clipobjectval[MAXCLIPNUM];
+
+typedef struct
+{
+ int32_t sx, sy, z;
+ short a, picnum;
+ int8_t dashade;
+ uint8_t dapalnum, dastat, pagesleft;
+ int32_t cx1, cy1, cx2, cy2;
+} permfifotype;
+static permfifotype permfifo[MAXPERMS];
+static int32_t permhead = 0, permtail = 0;
+
+//FCS: Num walls to potentially render.
+short numscans ;
+
+short numbunches;
+
+//FCS: Number of colums to draw. ALWAYS set to the screen dimension width.
+short numhits;
+
+short editstatus = 0;
+short searchit;
+int32_t searchx = -1, searchy; /* search input */
+short searchsector, searchwall, searchstat; /* search output */
+
+int32_t numtilefiles, artfil = -1, artfilnum, artfilplc;
+
+static uint8_t inpreparemirror = 0;
+static int32_t mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2;
+
+int32_t totalclocklock;
+
+uint16_t mapCRC;
+
+#include "draw.h"
+
+static __inline int32_t nsqrtasm(uint32_t param)
+{
+ uint16_t *shlookup_a = (uint16_t*)shlookup;
+ uint16_t *sqrtable_a = (uint16_t*)sqrtable;
+ uint16_t cx;
+
+ if (param & 0xff000000)
+ cx = shlookup_a[(param>>24)+4096];
+ else
+ cx = shlookup_a[param>>12];
+
+ param = param >> (cx&0xff);
+ param = ((param&0xffff0000)|sqrtable_a[param]);
+ param = param >> ((cx&0xff00)>>8);
+
+ return param;
+}
+
+static __inline int32_t krecipasm(int32_t i)
+{ // Ken did this
+ float f = (float)i;
+ i = *(int32_t *)&f;
+ return((reciptable[(i>>12)&2047]>>(((i-0x3f800000)>>23)&31))^(i>>31));
+}
+
+
+
+static __inline int32_t getclipmask(int32_t a, int32_t b, int32_t c, int32_t d)
+{ // Ken did this
+ d = ((a<0)*8) + ((b<0)*4) + ((c<0)*2) + (d<0);
+ return(((d<<4)^0xf0)|d);
+}
+
+//
+// krecip
+//
+int32_t krecip(int32_t num)
+{
+ return(krecipasm(num));
+}
+
+uint16_t _swap16(uint16_t D)
+{
+ return((D<<8)|(D>>8));
+}
+
+unsigned int _swap32(unsigned int D)
+{
+ return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24));
+}
+
+/*
+ FCS:
+ Scan through sectors using portals (a portal is wall with a nextsector attribute >= 0).
+ Flood is prevented if a portal does not face the POV.
+ */
+static void scansector (short sectnum)
+{
+ walltype *wal, *wal2;
+ spritetype *spr;
+ int32_t xs, ys, x1, y1, x2, y2, xp1, yp1, xp2=0, yp2=0, tempint;
+ short z, zz, startwall, endwall, numscansbefore, scanfirst, bunchfrst;
+ short nextsectnum;
+
+ //The stack storing sectors to visit.
+ short sectorsToVisit[256], numSectorsToVisit;
+
+
+ if (sectnum < 0)
+ return;
+
+ if (automapping)
+ show2dsector[sectnum>>3] |= pow2char[sectnum&7];
+
+ sectorsToVisit[0] = sectnum;
+ numSectorsToVisit = 1;
+ do
+ {
+ sectnum = sectorsToVisit[--numSectorsToVisit];
+
+ //Add every script in the current sector as potentially visible.
+ for(z=headspritesect[sectnum]; z>=0; z=nextspritesect[z])
+ {
+ spr = &sprite[z];
+ if ((((spr->cstat&0x8000) == 0) || (showinvisibility)) &&
+ (spr->xrepeat > 0) && (spr->yrepeat > 0) &&
+ (spritesortcnt < MAXSPRITESONSCREEN))
+ {
+ xs = spr->x-globalposx;
+ ys = spr->y-globalposy;
+ if ((spr->cstat&48) || (xs*cosglobalang+ys*singlobalang > 0))
+ {
+ copybufbyte(spr,&tsprite[spritesortcnt],sizeof(spritetype));
+ tsprite[spritesortcnt++].owner = z;
+ }
+ }
+ }
+
+ //Mark the current sector bit as "visited" in the bitvector
+ visitedSectors[sectnum>>3] |= pow2char[sectnum&7];
+
+ bunchfrst = numbunches;
+ numscansbefore = numscans;
+
+ startwall = sector[sectnum].wallptr;
+ endwall = startwall + sector[sectnum].wallnum;
+ scanfirst = numscans;
+ for(z=startwall,wal=&wall[z]; z<endwall; z++,wal++)
+ {
+ nextsectnum = wal->nextsector;
+
+ wal2 = &wall[wal->point2];
+
+ // In camera space the center is the player.
+ // Tranform the 2 Wall endpoints (x,y) from worldspace to camera space.
+ // After that we have two vectors starting from the camera and going to the endpoints (x1,y1) and (x2,y2).
+ x1 = wal->x-globalposx;
+ y1 = wal->y-globalposy;
+
+ x2 = wal2->x-globalposx;
+ y2 = wal2->y-globalposy;
+
+ // If this is a portal...
+ if ((nextsectnum >= 0) && ((wal->cstat&32) == 0))
+ //If this portal has not been visited yet.
+ if ((visitedSectors[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)
+ {
+ //Cross product -> Z component
+ tempint = x1*y2-x2*y1;
+
+ // Using cross product, determine if the portal is facing us or not.
+ // If it is: Add it to the stack and bump the stack counter.
+ // This line is equivalent to tempint < 0x40000
+ if (((uint32_t)tempint+262144) < 524288) // ??? What is this test ?? How acute the angle is ?
+ {
+ //(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1) is the squared length of the wall
+ // ??? What is this test ?? How acute the angle is ?
+ if (mulscale5(tempint,tempint) <= (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
+ sectorsToVisit[numSectorsToVisit++] = nextsectnum;
+ }
+ }
+
+ // Rotate the wall endpoints vectors according to the player orientation.
+ // This is a regular rotation matrix using [29.3] fixed point.
+ if ((z == startwall) || (wall[z-1].point2 != z))
+ {
+ //If this is the first endpoint of the bunch, rotate: This is a standard cos sin 2D rotation matrix projection
+ xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
+ yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
+ }
+ else
+ {
+ //If this is NOT the first endpoint, Save the coordinate for next loop.
+ xp1 = xp2;
+ yp1 = yp2;
+ }
+
+ // Rotate: This is a standard cos sin 2D rotation matrix projection
+ xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
+ yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
+
+
+
+ // Equivalent of a near plane clipping ?
+ if ((yp1 < 256) && (yp2 < 256)) goto skipitaddwall;
+
+ /* If wall's NOT facing you */
+ if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0) goto skipitaddwall;
+
+ // The wall is still not eligible for rendition: Let's do some more Frustrum culling !!
+ if (xp1 >= -yp1){
+
+ if ((xp1 > yp1) || (yp1 == 0))
+ goto skipitaddwall;
+
+ //Project the point onto screen and see in which column it belongs.
+ pvWalls[numscans].screenSpaceCoo[0][VEC_COL] = halfxdimen + scale(xp1,halfxdimen,yp1);
+ if (xp1 >= 0)
+ pvWalls[numscans].screenSpaceCoo[0][VEC_COL]++; /* Fix for SIGNED divide */
+
+ if (pvWalls[numscans].screenSpaceCoo[0][VEC_COL] >= xdimen)
+ pvWalls[numscans].screenSpaceCoo[0][VEC_COL] = xdimen-1;
+
+ pvWalls[numscans].screenSpaceCoo[0][VEC_DIST] = yp1;
+ }
+ else{
+
+ if (xp2 < -yp2)
+ goto skipitaddwall;
+
+ pvWalls[numscans].screenSpaceCoo[0][VEC_COL] = 0;
+ tempint = yp1-yp2+xp1-xp2;
+
+ if (tempint == 0)
+ goto skipitaddwall;
+
+ pvWalls[numscans].screenSpaceCoo[0][VEC_DIST] = yp1 + scale(yp2-yp1,xp1+yp1,tempint);
+ }
+
+ if (pvWalls[numscans].screenSpaceCoo[0][VEC_DIST] < 256)
+ goto skipitaddwall;
+
+ if (xp2 <= yp2){
+
+ if ((xp2 < -yp2) || (yp2 == 0)) goto skipitaddwall;
+ pvWalls[numscans].screenSpaceCoo[1][VEC_COL] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
+ if (xp2 >= 0) pvWalls[numscans].screenSpaceCoo[1][VEC_COL]++; /* Fix for SIGNED divide */
+ if (pvWalls[numscans].screenSpaceCoo[1][VEC_COL] >= xdimen) pvWalls[numscans].screenSpaceCoo[1][VEC_COL] = xdimen-1;
+ pvWalls[numscans].screenSpaceCoo[1][VEC_DIST] = yp2;
+ }
+ else{
+
+ if (xp1 > yp1) goto skipitaddwall;
+ pvWalls[numscans].screenSpaceCoo[1][VEC_COL] = xdimen-1;
+ tempint = xp2-xp1+yp1-yp2;
+ if (tempint == 0) goto skipitaddwall;
+ pvWalls[numscans].screenSpaceCoo[1][VEC_DIST] = yp1 + scale(yp2-yp1,yp1-xp1,tempint);
+ }
+ if ((pvWalls[numscans].screenSpaceCoo[1][VEC_DIST] < 256) || (pvWalls[numscans].screenSpaceCoo[0][VEC_COL] > pvWalls[numscans].screenSpaceCoo[1][VEC_COL])) goto skipitaddwall;
+
+ // Made it all the way!
+ // Time to add this wall information to the stack of wall potentially visible.
+ pvWalls[numscans].sectorId = sectnum;
+ pvWalls[numscans].worldWallId = z;
+
+ //Save the camera space wall endpoints coordinate (camera origin at player location + rotated according to player orientation).
+ pvWalls[numscans].cameraSpaceCoo[0][VEC_X] = xp1;
+ pvWalls[numscans].cameraSpaceCoo[0][VEC_Y] = yp1;
+ pvWalls[numscans].cameraSpaceCoo[1][VEC_X] = xp2;
+ pvWalls[numscans].cameraSpaceCoo[1][VEC_Y] = yp2;
+
+
+ bunchWallsList[numscans] = numscans+1;
+ numscans++;
+
+skipitaddwall:
+
+ if ((wall[z].point2 < z) && (scanfirst < numscans))
+ {
+ bunchWallsList[numscans-1] = scanfirst;
+ scanfirst = numscans;
+ }
+ }
+
+ //FCS: TODO rename this p2[] to bunchList[] or something like that. This name is an abomination
+ // DONE, p2 is now called "bunchWallsList".
+
+ //Break down the list of walls for this sector into bunchs. Since a bunch is a
+ // continuously visible list of wall: A sector can generate many bunches.
+ for(z=numscansbefore; z<numscans; z++)
+ {
+ if ((wall[pvWalls[z].worldWallId].point2 !=
+ pvWalls[bunchWallsList[z]].worldWallId) || (pvWalls[z].screenSpaceCoo[1][VEC_COL] >= pvWalls[bunchWallsList[z]].screenSpaceCoo[0][VEC_COL]))
+ {
+ // Create an entry in the bunch list
+ bunchfirst[numbunches++] = bunchWallsList[z];
+
+ //Mark the end of the bunch wall list.
+ bunchWallsList[z] = -1;
+ }
+ }
+
+ //For each bunch, find the last wall and cache it in bunchlast.
+ for(z=bunchfrst; z<numbunches; z++)
+ {
+ for(zz=bunchfirst[z]; bunchWallsList[zz]>=0; zz=bunchWallsList[zz]);
+ bunchlast[z] = zz;
+ }
+
+ } while (numSectorsToVisit > 0);
+ // do this until the stack of sectors to visit if empty.
+}
+
+/*
+ FCS:
+
+ Goal : ????
+ param 1: Z is the wallID in the list of potentially visible walls.
+ param 2: Only used to lookup the xrepeat attribute of the wall.
+
+*/
+static void prepwall(int32_t z, walltype *wal)
+{
+ int32_t i, l=0, ol=0, splc, sinc, x, topinc, top, botinc, bot, walxrepeat;
+ vector_t* wallCoo = pvWalls[z].cameraSpaceCoo;
+
+ walxrepeat = (wal->xrepeat<<3);
+
+ /* lwall calculation */
+ i = pvWalls[z].screenSpaceCoo[0][VEC_COL]-halfxdimen;
+
+ //Let's use some of the camera space wall coordinate now.
+ topinc = -(wallCoo[0][VEC_Y]>>2);
+ botinc = ((wallCoo[1][VEC_Y]-wallCoo[0][VEC_Y])>>8);
+
+ top = mulscale5(wallCoo[0][VEC_X],xdimen)+mulscale2(topinc,i);
+ bot = mulscale11(wallCoo[0][VEC_X]-wallCoo[1][VEC_X],xdimen)+mulscale2(botinc,i);
+
+ splc = mulscale19(wallCoo[0][VEC_Y],xdimscale);
+ sinc = mulscale16(wallCoo[1][VEC_Y]-wallCoo[0][VEC_Y],xdimscale);
+
+ //X screenspce column of point Z.
+ x = pvWalls[z].screenSpaceCoo[0][VEC_COL];
+
+ if (bot != 0)
+ {
+ l = divscale12(top,bot);
+ swall[x] = mulscale21(l,sinc)+splc;
+ l *= walxrepeat;
+ lwall[x] = (l>>18);
+ }
+
+ //If the wall is less than 4 column wide.
+ while (x+4 <= pvWalls[z].screenSpaceCoo[1][VEC_COL])
+ {
+ top += topinc;
+ bot += botinc;
+ if (bot != 0)
+ {
+ ol = l;
+ l = divscale12(top,bot);
+ swall[x+4] = mulscale21(l,sinc)+splc;
+ l *= walxrepeat;
+ lwall[x+4] = (l>>18);
+ }
+ i = ((ol+l)>>1);
+ lwall[x+2] = (i>>18);
+ lwall[x+1] = ((ol+i)>>19);
+ lwall[x+3] = ((l+i)>>19);
+ swall[x+2] = ((swall[x]+swall[x+4])>>1);
+ swall[x+1] = ((swall[x]+swall[x+2])>>1);
+ swall[x+3] = ((swall[x+4]+swall[x+2])>>1);
+ x += 4;
+ }
+
+ //If the wall is less than 2 columns wide.
+ if (x+2 <= pvWalls[z].screenSpaceCoo[1][VEC_COL])
+ {
+ top += (topinc>>1);
+ bot += (botinc>>1);
+ if (bot != 0)
+ {
+ ol = l;
+ l = divscale12(top,bot);
+ swall[x+2] = mulscale21(l,sinc)+splc;
+ l *= walxrepeat;
+ lwall[x+2] = (l>>18);
+ }
+ lwall[x+1] = ((l+ol)>>19);
+ swall[x+1] = ((swall[x]+swall[x+2])>>1);
+ x += 2;
+ }
+
+ //The wall is 1 column wide.
+ if (x+1 <= pvWalls[z].screenSpaceCoo[1][VEC_COL])
+ {
+ bot += (botinc>>2);
+ if (bot != 0)
+ {
+ l = divscale12(top+(topinc>>2),bot);
+ swall[x+1] = mulscale21(l,sinc)+splc;
+ lwall[x+1] = mulscale18(l,walxrepeat);
+ }
+ }
+
+ if (lwall[pvWalls[z].screenSpaceCoo[0][VEC_COL]] < 0)
+ lwall[pvWalls[z].screenSpaceCoo[0][VEC_COL]] = 0;
+
+ if ((lwall[pvWalls[z].screenSpaceCoo[1][VEC_COL]] >= walxrepeat) && (walxrepeat))
+ lwall[pvWalls[z].screenSpaceCoo[1][VEC_COL]] = walxrepeat-1;
+
+ if (wal->cstat&8)
+ {
+ walxrepeat--;
+ for(x=pvWalls[z].screenSpaceCoo[0][VEC_COL]; x<=pvWalls[z].screenSpaceCoo[1][VEC_COL]; x++)
+ lwall[x] = walxrepeat-lwall[x];
+ }
+}
+
+
+static int32_t getpalookup(int32_t davis, int32_t dashade)
+{
+ return(min(max(dashade+(davis>>8),0),numpalookups-1));
+}
+
+
+static void hline (int32_t xr, int32_t yp)
+{
+ int32_t xl, r, s;
+
+ xl = lastx[yp];
+
+ if (xl > xr)
+ return;
+
+ r = horizlookup2[yp-globalhoriz+horizycent];
+ asm1 = globalx1*r;
+ asm2 = globaly2*r;
+ s = (getpalookup(mulscale16(r,globvis),globalshade)<<8);
+
+ hlineasm4(xr-xl,s,globalx2*r+globalypanning,globaly1*r+globalxpanning,ylookup[yp]+xr+frameoffset);
+}
+
+
+static void slowhline (int32_t xr, int32_t yp)
+{
+ int32_t xl, r;
+
+ xl = lastx[yp];
+ if (xl > xr) return;
+ r = horizlookup2[yp-globalhoriz+horizycent];
+ asm1 = globalx1*r;
+ asm2 = globaly2*r;
+
+ asm3 = (int32_t)globalpalwritten + (getpalookup(mulscale16(r,globvis),globalshade)<<8);
+ if (!(globalorientation&256))
+ {
+ mhline(globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,
+ globalx2*r+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
+ return;
+ }
+ thline(globalbufplc,globaly1*r+globalxpanning-asm1*(xr-xl),(xr-xl)<<16,0L,globalx2*r+globalypanning-asm2*(xr-xl),ylookup[yp]+xl+frameoffset);
+ transarea += (xr-xl);
+}
+
+
+
+
+
+/* renders non-parallaxed ceilings. --ryan. */
+static void ceilscan (int32_t x1, int32_t x2, int32_t sectnum)
+{
+ int32_t i, j, ox, oy, x, y1, y2, twall, bwall;
+ sectortype *sec;
+
+ sec = &sector[sectnum];
+
+ if (palookup[sec->ceilingpal] != globalpalwritten)
+ globalpalwritten = palookup[sec->ceilingpal];
+
+
+ globalzd = sec->ceilingz-globalposz;
+
+
+ if (globalzd > 0)
+ return;
+
+
+ globalpicnum = sec->ceilingpicnum;
+
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
+ globalpicnum = 0;
+
+ setgotpic(globalpicnum);
+
+ //Check the tile dimension are valid.
+ if ((tiles[globalpicnum].dim.width <= 0) ||
+ (tiles[globalpicnum].dim.height <= 0))
+ return;
+
+ if (tiles[globalpicnum].animFlags&192)
+ globalpicnum += animateoffs(globalpicnum);
+
+ TILE_MakeAvailable(globalpicnum);
+
+ globalbufplc = tiles[globalpicnum].data;
+
+ globalshade = (int32_t)sec->ceilingshade;
+ globvis = globalcisibility;
+ if (sec->visibility != 0)
+ globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+
+ globalorientation = (int32_t)sec->ceilingstat;
+
+
+ if ((globalorientation&64) == 0){
+ globalx1 = singlobalang;
+ globalx2 = singlobalang;
+ globaly1 = cosglobalang;
+ globaly2 = cosglobalang;
+ globalxpanning = (globalposx<<20);
+ globalypanning = -(globalposy<<20);
+ }
+ else{
+ j = sec->wallptr;
+ ox = wall[wall[j].point2].x - wall[j].x;
+ oy = wall[wall[j].point2].y - wall[j].y;
+ i = nsqrtasm(ox*ox+oy*oy);
+
+ if (i == 0)
+ i = 1024;
+ else
+ i = 1048576/i;
+
+ globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
+ globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
+ globalx2 = -globalx1;
+ globaly2 = -globaly1;
+
+ ox = ((wall[j].x-globalposx)<<6);
+ oy = ((wall[j].y-globalposy)<<6);
+ i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
+ j = dmulscale14(ox,cosglobalang,oy,singlobalang);
+ ox = i;
+ oy = j;
+ globalxpanning = globalx1*ox - globaly1*oy;
+ globalypanning = globaly2*ox + globalx2*oy;
+ }
+
+ globalx2 = mulscale16(globalx2,viewingrangerecip);
+ globaly1 = mulscale16(globaly1,viewingrangerecip);
+ globalxshift = (8-(picsiz[globalpicnum]&15));
+ globalyshift = (8-(picsiz[globalpicnum]>>4));
+ if (globalorientation&8) {
+ globalxshift++;
+ globalyshift++;
+ }
+
+ if ((globalorientation&0x4) > 0){
+ i = globalxpanning;
+ globalxpanning = globalypanning;
+ globalypanning = i;
+ i = globalx2;
+ globalx2 = -globaly1;
+ globaly1 = -i;
+ i = globalx1;
+ globalx1 = globaly2;
+ globaly2 = i;
+ }
+ if ((globalorientation&0x10) > 0){
+ globalx1 = -globalx1;
+ globaly1 = -globaly1;
+ globalxpanning = -globalxpanning;
+ }
+ if ((globalorientation&0x20) > 0){
+ globalx2 = -globalx2;
+ globaly2 = -globaly2;
+ globalypanning = -globalypanning;
+ }
+
+ globalx1 <<= globalxshift;
+ globaly1 <<= globalxshift;
+ globalx2 <<= globalyshift;
+ globaly2 <<= globalyshift;
+ globalxpanning <<= globalxshift;
+ globalypanning <<= globalyshift;
+ globalxpanning += (((int32_t)sec->ceilingxpanning)<<24);
+ globalypanning += (((int32_t)sec->ceilingypanning)<<24);
+ globaly1 = (-globalx1-globaly1)*halfxdimen;
+ globalx2 = (globalx2-globaly2)*halfxdimen;
+
+ sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
+
+ globalx2 += globaly2*(x1-1);
+ globaly1 += globalx1*(x1-1);
+ globalx1 = mulscale16(globalx1,globalzd);
+ globalx2 = mulscale16(globalx2,globalzd);
+ globaly1 = mulscale16(globaly1,globalzd);
+ globaly2 = mulscale16(globaly2,globalzd);
+ globvis = klabs(mulscale10(globvis,globalzd));
+
+ if (!(globalorientation&0x180))
+ {
+ y1 = umost[x1];
+ y2 = y1;
+ for(x=x1; x<=x2; x++)
+ {
+ twall = umost[x]-1;
+ bwall = min(uplc[x],dmost[x]);
+ if (twall < bwall-1)
+ {
+ if (twall >= y2)
+ {
+ while (y1 < y2-1) hline(x-1,++y1);
+ y1 = twall;
+ }
+ else
+ {
+ while (y1 < twall)
+ hline(x-1,++y1);
+ while (y1 > twall)
+ lastx[y1--] = x;
+ }
+ while (y2 > bwall)
+ hline(x-1,--y2);
+ while (y2 < bwall)
+ lastx[y2++] = x;
+ }
+ else
+ {
+ while (y1 < y2-1)
+ hline(x-1,++y1);
+ if (x == x2) {
+ globalx2 += globaly2;
+ globaly1 += globalx1;
+ break;
+ }
+ y1 = umost[x+1];
+ y2 = y1;
+ }
+ globalx2 += globaly2;
+ globaly1 += globalx1;
+ }
+ while (y1 < y2-1) hline(x2,++y1);
+ faketimerhandler();
+ return;
+ }
+
+ switch(globalorientation&0x180)
+ {
+ case 128:
+ msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
+ break;
+ case 256:
+ settrans(TRANS_NORMAL);
+ tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
+ break;
+ case 384:
+ settrans(TRANS_REVERSE);
+ tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
+ break;
+ }
+
+ y1 = umost[x1];
+ y2 = y1;
+ for(x=x1; x<=x2; x++)
+ {
+ twall = umost[x]-1;
+ bwall = min(uplc[x],dmost[x]);
+ if (twall < bwall-1)
+ {
+ if (twall >= y2)
+ {
+ while (y1 < y2-1) slowhline(x-1,++y1);
+ y1 = twall;
+ }
+ else
+ {
+ while (y1 < twall) slowhline(x-1,++y1);
+ while (y1 > twall) lastx[y1--] = x;
+ }
+ while (y2 > bwall) slowhline(x-1,--y2);
+ while (y2 < bwall) lastx[y2++] = x;
+ }
+ else
+ {
+ while (y1 < y2-1) slowhline(x-1,++y1);
+ if (x == x2) {
+ globalx2 += globaly2;
+ globaly1 += globalx1;
+ break;
+ }
+ y1 = umost[x+1];
+ y2 = y1;
+ }
+ globalx2 += globaly2;
+ globaly1 += globalx1;
+ }
+ while (y1 < y2-1) slowhline(x2,++y1);
+ faketimerhandler();
+}
+
+
+/* renders non-parallaxed floors. --ryan. */
+static void florscan (int32_t x1, int32_t x2, int32_t sectnum)
+{
+ int32_t i, j, ox, oy, x, y1, y2, twall, bwall;
+ sectortype *sec;
+
+ //Retrieve the sector object
+ sec = &sector[sectnum];
+
+ //Retrieve the floor palette.
+ if (palookup[sec->floorpal] != globalpalwritten)
+ globalpalwritten = palookup[sec->floorpal];
+
+ globalzd = globalposz-sec->floorz;
+
+ //We are UNDER the floor: Do NOT render anything.
+ if (globalzd > 0)
+ return;
+
+ //Retrive the floor texture.
+ globalpicnum = sec->floorpicnum;
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
+ globalpicnum = 0;
+
+ //Lock the floor texture
+ setgotpic(globalpicnum);
+
+
+ //This tile has unvalid dimensions ( negative)
+ if ((tiles[globalpicnum].dim.width <= 0) ||
+ (tiles[globalpicnum].dim.height <= 0))
+ return;
+
+ //If this is an animated texture: Animate it.
+ if (tiles[globalpicnum].animFlags&192)
+ globalpicnum += animateoffs(globalpicnum);
+
+ //If the texture is not in RAM: Load it !!
+ TILE_MakeAvailable(globalpicnum);
+
+ //Check where is the texture in RAM
+ globalbufplc = tiles[globalpicnum].data;
+
+ //Retrieve the shade of the sector (illumination level).
+ globalshade = (int32_t)sec->floorshade;
+
+ globvis = globalcisibility;
+ if (sec->visibility != 0)
+ globvis = mulscale4(globvis,(int32_t)((uint8_t)(sec->visibility+16)));
+
+
+ globalorientation = (int32_t)sec->floorstat;
+
+
+ if ((globalorientation&64) == 0)
+ {
+ globalx1 = singlobalang;
+ globalx2 = singlobalang;
+ globaly1 = cosglobalang;
+ globaly2 = cosglobalang;
+ globalxpanning = (globalposx<<20);
+ globalypanning = -(globalposy<<20);
+ }
+ else
+ {
+ j = sec->wallptr;
+ ox = wall[wall[j].point2].x - wall[j].x;
+ oy = wall[wall[j].point2].y - wall[j].y;
+ i = nsqrtasm(ox*ox+oy*oy);
+ if (i == 0)
+ i = 1024;
+ else
+ i = 1048576/i;
+ globalx1 = mulscale10(dmulscale10(ox,singlobalang,-oy,cosglobalang),i);
+ globaly1 = mulscale10(dmulscale10(ox,cosglobalang,oy,singlobalang),i);
+ globalx2 = -globalx1;
+ globaly2 = -globaly1;
+
+ ox = ((wall[j].x-globalposx)<<6);
+ oy = ((wall[j].y-globalposy)<<6);
+ i = dmulscale14(oy,cosglobalang,-ox,singlobalang);
+ j = dmulscale14(ox,cosglobalang,oy,singlobalang);
+ ox = i;
+ oy = j;
+ globalxpanning = globalx1*ox - globaly1*oy;
+ globalypanning = globaly2*ox + globalx2*oy;
+ }
+
+
+ globalx2 = mulscale16(globalx2,viewingrangerecip);
+ globaly1 = mulscale16(globaly1,viewingrangerecip);
+ globalxshift = (8-(picsiz[globalpicnum]&15));
+ globalyshift = (8-(picsiz[globalpicnum]>>4));
+ if (globalorientation&8) {
+ globalxshift++;
+ globalyshift++;
+ }
+
+ if ((globalorientation&0x4) > 0)
+ {
+ i = globalxpanning;
+ globalxpanning = globalypanning;
+ globalypanning = i;
+ i = globalx2;
+ globalx2 = -globaly1;
+ globaly1 = -i;
+ i = globalx1;
+ globalx1 = globaly2;
+ globaly2 = i;
+ }
+
+
+ if ((globalorientation&0x10) > 0){
+ globalx1 = -globalx1;
+ globaly1 = -globaly1;
+ globalxpanning = -globalxpanning;
+ }
+
+ if ((globalorientation&0x20) > 0){
+ globalx2 = -globalx2;
+ globaly2 = -globaly2;
+ globalypanning = -globalypanning;
+ }
+
+
+ globalx1 <<= globalxshift;
+ globaly1 <<= globalxshift;
+ globalx2 <<= globalyshift;
+ globaly2 <<= globalyshift;
+ globalxpanning <<= globalxshift;
+ globalypanning <<= globalyshift;
+ globalxpanning += (((int32_t)sec->floorxpanning)<<24);
+ globalypanning += (((int32_t)sec->floorypanning)<<24);
+ globaly1 = (-globalx1-globaly1)*halfxdimen;
+ globalx2 = (globalx2-globaly2)*halfxdimen;
+
+ //Setup the drawing routine paramters
+ sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
+
+ globalx2 += globaly2*(x1-1);
+ globaly1 += globalx1*(x1-1);
+ globalx1 = mulscale16(globalx1,globalzd);
+ globalx2 = mulscale16(globalx2,globalzd);
+ globaly1 = mulscale16(globaly1,globalzd);
+ globaly2 = mulscale16(globaly2,globalzd);
+ globvis = klabs(mulscale10(globvis,globalzd));
+
+ if (!(globalorientation&0x180))
+ {
+ y1 = max(dplc[x1],umost[x1]);
+ y2 = y1;
+ for(x=x1; x<=x2; x++)
+ {
+ twall = max(dplc[x],umost[x])-1;
+ bwall = dmost[x];
+ if (twall < bwall-1)
+ {
+ if (twall >= y2)
+ {
+ while (y1 < y2-1)
+ hline(x-1,++y1);
+ y1 = twall;
+ }
+ else
+ {
+ while (y1 < twall)
+ hline(x-1,++y1);
+ while (y1 > twall)
+ lastx[y1--] = x;
+ }
+ while (y2 > bwall)
+ hline(x-1,--y2);
+ while (y2 < bwall)
+ lastx[y2++] = x;
+ }
+ else
+ {
+ while (y1 < y2-1) hline(x-1,++y1);
+ if (x == x2) {
+ globalx2 += globaly2;
+ globaly1 += globalx1;
+ break;
+ }
+ y1 = max(dplc[x+1],umost[x+1]);
+ y2 = y1;
+ }
+ globalx2 += globaly2;
+ globaly1 += globalx1;
+ }
+ while (y1 < y2-1)
+ hline(x2,++y1);
+
+ faketimerhandler();
+ return;
+ }
+
+ switch(globalorientation&0x180)
+ {
+ case 128:
+ msethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
+ break;
+ case 256:
+ settrans(TRANS_NORMAL);
+ tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
+ break;
+ case 384:
+ settrans(TRANS_REVERSE);
+ tsethlineshift(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4);
+ break;
+ }
+
+ y1 = max(dplc[x1],umost[x1]);
+ y2 = y1;
+ for(x=x1; x<=x2; x++)
+ {
+ twall = max(dplc[x],umost[x])-1;
+ bwall = dmost[x];
+ if (twall < bwall-1)
+ {
+ if (twall >= y2)
+ {
+ while (y1 < y2-1) slowhline(x-1,++y1);
+ y1 = twall;
+ }
+ else
+ {
+ while (y1 < twall)
+ slowhline(x-1,++y1);
+ while (y1 > twall)
+ lastx[y1--] = x;
+ }
+ while (y2 > bwall)
+ slowhline(x-1,--y2);
+ while (y2 < bwall)
+ lastx[y2++] = x;
+ }
+ else
+ {
+ while (y1 < y2-1)
+ slowhline(x-1,++y1);
+ if (x == x2) {
+ globalx2 += globaly2;
+ globaly1 += globalx1;
+ break;
+ }
+ y1 = max(dplc[x+1],umost[x+1]);
+ y2 = y1;
+ }
+ globalx2 += globaly2;
+ globaly1 += globalx1;
+ }
+ while (y1 < y2-1)
+ slowhline(x2,++y1);
+
+ faketimerhandler();
+}
+
+
+/*
+ * renders walls and parallaxed skies/floors. Look at parascan() for the
+ * higher level of parallaxing.
+ *
+ * x1 == offset of leftmost pixel of wall. 0 is left of surface.
+ * x2 == offset of rightmost pixel of wall. 0 is left of surface.
+ *
+ * apparently, walls are always vertical; there are sloping functions
+ * (!!!) er...elsewhere. Only the sides need be vertical, as the top and
+ * bottom of the polygon will need to be angled as the camera perspective
+ * shifts (user spins in a circle, etc.)
+ *
+ * uwal is an array of the upper most pixels, and dwal are the lower most.
+ * This must be a list, as the top and bottom of the polygon are not
+ * necessarily horizontal lines.
+ *
+ * So, the screen coordinate of the top left of a wall is specified by
+ * uwal[x1], the bottom left by dwal[x1], the top right by uwal[x2], and
+ * the bottom right by dwal[x2]. Every physical point on the edge of the
+ * wall in between is specified by traversing those arrays, one pixel per
+ * element.
+ *
+ * --ryan.
+ */
+static void wallscan(int32_t x1, int32_t x2,
+ int16_t *uwal, int16_t *dwal,
+ int32_t *swal, int32_t *lwal)
+{
+ int32_t x, xnice, ynice;
+ intptr_t i;
+ uint8_t* fpalookup;
+ int32_t y1ve[4], y2ve[4], u4, d4, z, tileWidth, tsizy;
+ uint8_t bad;
+
+ tileWidth = tiles[globalpicnum].dim.width;
+ tsizy = tiles[globalpicnum].dim.height;
+
+ setgotpic(globalpicnum);
+
+ if ((tileWidth <= 0) || (tsizy <= 0))
+ return;
+
+ if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen))
+ return;
+
+ if ((dwal[x1] < 0) && (dwal[x2] < 0))
+ return;
+
+ TILE_MakeAvailable(globalpicnum);
+
+ xnice = (pow2long[picsiz[globalpicnum]&15] == tileWidth);
+ if (xnice)
+ tileWidth--;
+
+ ynice = (pow2long[picsiz[globalpicnum]>>4] == tsizy);
+ if (ynice)
+ tsizy = (picsiz[globalpicnum]>>4);
+
+ fpalookup = palookup[globalpal];
+
+ setupvlineasm(globalshiftval);
+
+ //Starting on the left column of the wall, check the occlusion arrays.
+ x = x1;
+ while ((umost[x] > dmost[x]) && (x <= x2))
+ x++;
+
+ for(; (x<=x2)&&((x+frameoffset-(uint8_t*)NULL)&3); x++)
+ {
+ y1ve[0] = max(uwal[x],umost[x]);
+ y2ve[0] = min(dwal[x],dmost[x]);
+ if (y2ve[0] <= y1ve[0])
+ continue;
+
+ palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
+
+ bufplce[0] = lwal[x] + globalxpanning;
+
+ if (bufplce[0] >= tileWidth)
+ {
+ if (xnice == 0)
+ bufplce[0] %= tileWidth;
+ else
+ bufplce[0] &= tileWidth;
+ }
+
+ if (ynice == 0)
+ bufplce[0] *= tsizy;
+ else
+ bufplce[0] <<= tsizy;
+
+ vince[0] = swal[x]*globalyscale;
+ vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
+
+ vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+tiles[globalpicnum].data,x+frameoffset+ylookup[y1ve[0]]);
+ }
+
+ for(; x<=x2-3; x+=4)
+ {
+ bad = 0;
+ for(z=3; z>=0; z--)
+ {
+ y1ve[z] = max(uwal[x+z],umost[x+z]);
+ y2ve[z] = min(dwal[x+z],dmost[x+z])-1;
+
+ if (y2ve[z] < y1ve[z])
+ {
+ bad += pow2char[z];
+ continue;
+ }
+
+ i = lwal[x+z] + globalxpanning;
+ if (i >= tileWidth) {
+ if (xnice == 0) i %= tileWidth;
+ else i &= tileWidth;
+ }
+ if (ynice == 0)
+ i *= tsizy;
+ else
+ i <<= tsizy;
+ bufplce[z] = tiles[globalpicnum].data+i;
+
+ vince[z] = swal[x+z]*globalyscale;
+ vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
+ }
+
+ if (bad == 15)
+ continue;
+
+ palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
+ palookupoffse[3] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+3],globvis),globalshade)<<8);
+
+ if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
+ {
+ palookupoffse[1] = palookupoffse[0];
+ palookupoffse[2] = palookupoffse[0];
+ }
+ else
+ {
+ palookupoffse[1] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+1],globvis),globalshade)<<8);
+ palookupoffse[2] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+2],globvis),globalshade)<<8);
+ }
+
+ u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
+ d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
+
+ if ((bad != 0) || (u4 >= d4))
+ {
+ if (!(bad&1))
+ prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+x+frameoffset+0);
+ if (!(bad&2))
+ prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+x+frameoffset+1);
+ if (!(bad&4))
+ prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+x+frameoffset+2);
+ if (!(bad&8))
+ prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+x+frameoffset+3);
+ continue;
+ }
+
+ if (u4 > y1ve[0])
+ vplce[0] =prevlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+x+frameoffset+0);
+ if (u4 > y1ve[1])
+ vplce[1] = prevlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+x+frameoffset+1);
+ if (u4 > y1ve[2])
+ vplce[2] = prevlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+x+frameoffset+2);
+ if (u4 > y1ve[3])
+ vplce[3] = prevlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+x+frameoffset+3);
+
+ if (d4 >= u4)
+ vlineasm4(d4-u4+1,ylookup[u4]+x+frameoffset);
+
+ i = x+frameoffset+ylookup[d4+1];
+
+ if (y2ve[0] > d4)
+ prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
+ if (y2ve[1] > d4)
+ prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
+ if (y2ve[2] > d4)
+ prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
+ if (y2ve[3] > d4)
+ prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
+ }
+ for(; x<=x2; x++)
+ {
+ y1ve[0] = max(uwal[x],umost[x]);
+ y2ve[0] = min(dwal[x],dmost[x]);
+ if (y2ve[0] <= y1ve[0])
+ continue;
+
+ palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
+
+ bufplce[0] = lwal[x] + globalxpanning;
+ if (bufplce[0] >= tileWidth) {
+ if (xnice == 0)
+ bufplce[0] %= tileWidth;
+ else
+ bufplce[0] &= tileWidth;
+ }
+
+ if (ynice == 0) bufplce[0]
+ *= tsizy;
+ else
+ bufplce[0] <<= tsizy;
+
+ vince[0] = swal[x]*globalyscale;
+ vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
+
+ vlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+tiles[globalpicnum].data,x+frameoffset+ylookup[y1ve[0]]);
+ }
+ faketimerhandler();
+}
+
+
+/* this renders masking sprites. See wallscan(). --ryan. */
+static void maskwallscan(int32_t x1, int32_t x2,
+ short *uwal, short *dwal,
+ int32_t *swal, int32_t *lwal)
+{
+ int32_t x, startx, xnice, ynice;
+ intptr_t i;
+ uint8_t* fpalookup;
+ int32_t y1ve[4], y2ve[4], u4, d4, dax, z, tileWidth, tileHeight;
+ uint8_t* p;
+ uint8_t bad;
+
+ tileWidth = tiles[globalpicnum].dim.width;
+ tileHeight = tiles[globalpicnum].dim.height;
+ setgotpic(globalpicnum);
+
+ if ((tileWidth <= 0) || (tileHeight <= 0))
+ return;
+ if ((uwal[x1] > ydimen) && (uwal[x2] > ydimen))
+ return;
+ if ((dwal[x1] < 0) && (dwal[x2] < 0))
+ return;
+
+ TILE_MakeAvailable(globalpicnum);
+
+ startx = x1;
+
+ xnice = (pow2long[picsiz[globalpicnum]&15] == tileWidth);
+ if (xnice)
+ tileWidth = (tileWidth-1);
+
+ ynice = (pow2long[picsiz[globalpicnum]>>4] == tileHeight);
+ if (ynice)
+ tileHeight = (picsiz[globalpicnum]>>4);
+
+ fpalookup = palookup[globalpal];
+
+ setupmvlineasm(globalshiftval);
+
+ x = startx;
+ while ((startumost[x+windowx1] > startdmost[x+windowx1]) && (x <= x2)) x++;
+
+ p = x+frameoffset;
+
+ for(; (x<=x2)&&((p-(uint8_t*)NULL)&3); x++,p++)
+ {
+ y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
+ y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
+ if (y2ve[0] <= y1ve[0]) continue;
+
+ palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
+
+ bufplce[0] = lwal[x] + globalxpanning;
+ if (bufplce[0] >= tileWidth) {
+ if (xnice == 0) bufplce[0] %= tileWidth;
+ else bufplce[0] &= tileWidth;
+ }
+ if (ynice == 0)
+ bufplce[0] *= tileHeight;
+ else
+ bufplce[0] <<= tileHeight;
+
+ vince[0] = swal[x]*globalyscale;
+ vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
+
+ mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+tiles[globalpicnum].data,p+ylookup[y1ve[0]]);
+ }
+ for(; x<=x2-3; x+=4,p+=4)
+ {
+ bad = 0;
+ for(z=3,dax=x+3; z>=0; z--,dax--)
+ {
+ y1ve[z] = max(uwal[dax],startumost[dax+windowx1]-windowy1);
+ y2ve[z] = min(dwal[dax],startdmost[dax+windowx1]-windowy1)-1;
+ if (y2ve[z] < y1ve[z]) {
+ bad += pow2char[z];
+ continue;
+ }
+
+ i = lwal[dax] + globalxpanning;
+ if (i >= tileWidth) {
+ if (xnice == 0) i %= tileWidth;
+ else i &= tileWidth;
+ }
+
+ if (ynice == 0)
+ i *= tileHeight;
+ else
+ i <<= tileHeight;
+
+ bufplce[z] = tiles[globalpicnum].data+i;
+
+ vince[z] = swal[dax]*globalyscale;
+ vplce[z] = globalzd + vince[z]*(y1ve[z]-globalhoriz+1);
+ }
+ if (bad == 15) continue;
+
+ palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
+ palookupoffse[3] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+3],globvis),globalshade)<<8);
+
+ if ((palookupoffse[0] == palookupoffse[3]) && ((bad&0x9) == 0))
+ {
+ palookupoffse[1] = palookupoffse[0];
+ palookupoffse[2] = palookupoffse[0];
+ }
+ else
+ {
+ palookupoffse[1] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+1],globvis),globalshade)<<8);
+ palookupoffse[2] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x+2],globvis),globalshade)<<8);
+ }
+
+ u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
+ d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
+
+ if ((bad > 0) || (u4 >= d4))
+ {
+ if (!(bad&1)) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
+ if (!(bad&2)) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
+ if (!(bad&4)) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
+ if (!(bad&8)) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
+ continue;
+ }
+
+ if (u4 > y1ve[0]) vplce[0] = mvlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
+ if (u4 > y1ve[1]) vplce[1] = mvlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
+ if (u4 > y1ve[2]) vplce[2] = mvlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
+ if (u4 > y1ve[3]) vplce[3] = mvlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
+
+ if (d4 >= u4) mvlineasm4(d4-u4+1,ylookup[u4]+p);
+
+ i = p+ylookup[d4+1];
+ if (y2ve[0] > d4) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
+ if (y2ve[1] > d4) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
+ if (y2ve[2] > d4) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
+ if (y2ve[3] > d4) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
+ }
+ for(; x<=x2; x++,p++)
+ {
+ y1ve[0] = max(uwal[x],startumost[x+windowx1]-windowy1);
+ y2ve[0] = min(dwal[x],startdmost[x+windowx1]-windowy1);
+ if (y2ve[0] <= y1ve[0]) continue;
+
+ palookupoffse[0] = fpalookup+(getpalookup((int32_t)mulscale16(swal[x],globvis),globalshade)<<8);
+
+ bufplce[0] = lwal[x] + globalxpanning;
+ if (bufplce[0] >= tileWidth) {
+ if (xnice == 0) bufplce[0] %= tileWidth;
+ else bufplce[0] &= tileWidth;
+ }
+ if (ynice == 0)
+ bufplce[0] *= tileHeight;
+ else
+ bufplce[0] <<= tileHeight;
+
+ vince[0] = swal[x]*globalyscale;
+ vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
+
+ mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0]-1,vplce[0],bufplce[0]+tiles[globalpicnum].data,p+ylookup[y1ve[0]]);
+ }
+ faketimerhandler();
+}
+
+/* renders parallaxed skies/floors --ryan. */
+static void parascan(int32_t dax1, int32_t dax2, int32_t sectnum,uint8_t dastat, int32_t bunch)
+{
+ sectortype *sec;
+ int32_t j, k, l, m, n, x, z, wallnum, nextsectnum, globalhorizbak;
+ short *topptr, *botptr;
+
+ sectnum = pvWalls[bunchfirst[bunch]].sectorId;
+ sec = &sector[sectnum];
+
+ globalhorizbak = globalhoriz;
+ if (parallaxyscale != 65536)
+ globalhoriz = mulscale16(globalhoriz-(ydimen>>1),parallaxyscale) + (ydimen>>1);
+ globvis = globalpisibility;
+ /* globalorientation = 0L; */
+ if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+
+ if (dastat == 0)
+ {
+ globalpal = sec->ceilingpal;
+ globalpicnum = sec->ceilingpicnum;
+ globalshade = (int32_t)sec->ceilingshade;
+ globalxpanning = (int32_t)sec->ceilingxpanning;
+ globalypanning = (int32_t)sec->ceilingypanning;
+ topptr = umost;
+ botptr = uplc;
+ }
+ else
+ {
+ globalpal = sec->floorpal;
+ globalpicnum = sec->floorpicnum;
+ globalshade = (int32_t)sec->floorshade;
+ globalxpanning = (int32_t)sec->floorxpanning;
+ globalypanning = (int32_t)sec->floorypanning;
+ topptr = dplc;
+ botptr = dmost;
+ }
+
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
+
+ if (tiles[globalpicnum].animFlags&192)
+ globalpicnum += animateoffs(globalpicnum);
+
+ globalshiftval = (picsiz[globalpicnum]>>4);
+
+ if (pow2long[globalshiftval] != tiles[globalpicnum].dim.height)
+ globalshiftval++;
+ globalshiftval = 32-globalshiftval;
+ globalzd = (((tiles[globalpicnum].dim.height>>1)+parallaxyoffs)<<globalshiftval)+(globalypanning<<24);
+ globalyscale = (8<<(globalshiftval-19));
+ /*if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;*/
+
+ k = 11 - (picsiz[globalpicnum]&15) - pskybits;
+ x = -1;
+
+ for(z=bunchfirst[bunch]; z>=0; z=bunchWallsList[z])
+ {
+ wallnum = pvWalls[z].worldWallId;
+ nextsectnum = wall[wallnum].nextsector;
+
+ if (dastat == 0) j = sector[nextsectnum].ceilingstat;
+ else j = sector[nextsectnum].floorstat;
+
+ if ((nextsectnum < 0) || (wall[wallnum].cstat&32) || ((j&1) == 0))
+ {
+ if (x == -1) x = pvWalls[z].screenSpaceCoo[0][VEC_COL];
+
+ if (parallaxtype == 0)
+ {
+ n = mulscale16(xdimenrecip,viewingrange);
+ for(j=pvWalls[z].screenSpaceCoo[0][VEC_COL]; j<=pvWalls[z].screenSpaceCoo[1][VEC_COL]; j++)
+ lplc[j] = (((mulscale23(j-halfxdimen,n)+globalang)&2047)>>k);
+ }
+ else
+ {
+ for(j=pvWalls[z].screenSpaceCoo[0][VEC_COL]; j<=pvWalls[z].screenSpaceCoo[1][VEC_COL]; j++)
+ lplc[j] = ((((int32_t)radarang2[j]+globalang)&2047)>>k);
+ }
+ if (parallaxtype == 2)
+ {
+ n = mulscale16(xdimscale,viewingrange);
+ for(j=pvWalls[z].screenSpaceCoo[0][VEC_COL]; j<=pvWalls[z].screenSpaceCoo[1][VEC_COL]; j++)
+ swplc[j] = mulscale14(sintable[((int32_t)radarang2[j]+512)&2047],n);
+ }
+ else
+ clearbuf(&swplc[pvWalls[z].screenSpaceCoo[0][VEC_COL]],pvWalls[z].screenSpaceCoo[1][VEC_COL]-pvWalls[z].screenSpaceCoo[0][VEC_COL]+1,mulscale16(xdimscale,viewingrange));
+ }
+ else if (x >= 0)
+ {
+ l = globalpicnum;
+ m = (picsiz[globalpicnum]&15);
+ globalpicnum = l+pskyoff[lplc[x]>>m];
+
+ if (((lplc[x]^lplc[pvWalls[z].screenSpaceCoo[0][VEC_COL]-1])>>m) == 0)
+ wallscan(x,pvWalls[z].screenSpaceCoo[0][VEC_COL]-1,topptr,botptr,swplc,lplc);
+ else
+ {
+ j = x;
+ while (x < pvWalls[z].screenSpaceCoo[0][VEC_COL])
+ {
+ n = l+pskyoff[lplc[x]>>m];
+ if (n != globalpicnum)
+ {
+ wallscan(j,x-1,topptr,botptr,swplc,lplc);
+ j = x;
+ globalpicnum = n;
+ }
+ x++;
+ }
+ if (j < x)
+ wallscan(j,x-1,topptr,botptr,swplc,lplc);
+ }
+
+ globalpicnum = l;
+ x = -1;
+ }
+ }
+
+ if (x >= 0)
+ {
+ l = globalpicnum;
+ m = (picsiz[globalpicnum]&15);
+ globalpicnum = l+pskyoff[lplc[x]>>m];
+
+ if (((lplc[x]^lplc[pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL]])>>m) == 0)
+ wallscan(x,pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],topptr,botptr,swplc,lplc);
+ else
+ {
+ j = x;
+ while (x <= pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL])
+ {
+ n = l+pskyoff[lplc[x]>>m];
+ if (n != globalpicnum)
+ {
+ wallscan(j,x-1,topptr,botptr,swplc,lplc);
+ j = x;
+ globalpicnum = n;
+ }
+ x++;
+ }
+ if (j <= x)
+ wallscan(j,x,topptr,botptr,swplc,lplc);
+ }
+ globalpicnum = l;
+ }
+ globalhoriz = globalhorizbak;
+}
+
+
+#define BITSOFPRECISION 3 /* Don't forget to change this in A.ASM also! */
+static void grouscan (int32_t dax1, int32_t dax2, int32_t sectnum, uint8_t dastat)
+{
+ int32_t i, j, l, x, y, dx, dy, wx, wy, y1, y2, daz;
+ int32_t daslope, dasqr;
+ int32_t shoffs, shinc, m1, m2, *mptr1, *mptr2, *nptr1, *nptr2;
+ walltype *wal;
+ sectortype *sec;
+
+ sec = &sector[sectnum];
+
+ if (dastat == 0)
+ {
+ if (globalposz <= getceilzofslope((short) sectnum,globalposx,globalposy))
+ return; /* Back-face culling */
+ globalorientation = sec->ceilingstat;
+ globalpicnum = sec->ceilingpicnum;
+ globalshade = sec->ceilingshade;
+ globalpal = sec->ceilingpal;
+ daslope = sec->ceilingheinum;
+ daz = sec->ceilingz;
+ }
+ else
+ {
+ if (globalposz >= getflorzofslope((short) sectnum,globalposx,globalposy))
+ return; /* Back-face culling */
+ globalorientation = sec->floorstat;
+ globalpicnum = sec->floorpicnum;
+ globalshade = sec->floorshade;
+ globalpal = sec->floorpal;
+ daslope = sec->floorheinum;
+ daz = sec->floorz;
+ }
+
+ if ((tiles[globalpicnum].animFlags&192) != 0)
+ globalpicnum += animateoffs(globalpicnum);
+
+ setgotpic(globalpicnum);
+
+ if ((tiles[globalpicnum].dim.width <= 0) ||
+ (tiles[globalpicnum].dim.height <= 0))
+ return;
+
+ TILE_MakeAvailable(globalpicnum);
+
+ wal = &wall[sec->wallptr];
+ wx = wall[wal->point2].x - wal->x;
+ wy = wall[wal->point2].y - wal->y;
+ dasqr = krecipasm(nsqrtasm(wx*wx+wy*wy));
+ i = mulscale21(daslope,dasqr);
+ wx *= i;
+ wy *= i;
+
+ globalx = -mulscale19(singlobalang,xdimenrecip);
+ globaly = mulscale19(cosglobalang,xdimenrecip);
+ globalx1 = (globalposx<<8);
+ globaly1 = -(globalposy<<8);
+ i = (dax1-halfxdimen)*xdimenrecip;
+ globalx2 = mulscale16(cosglobalang<<4,viewingrangerecip) - mulscale27(singlobalang,i);
+ globaly2 = mulscale16(singlobalang<<4,viewingrangerecip) + mulscale27(cosglobalang,i);
+ globalzd = (xdimscale<<9);
+ globalzx = -dmulscale17(wx,globaly2,-wy,globalx2) + mulscale10(1-globalhoriz,globalzd);
+ globalz = -dmulscale25(wx,globaly,-wy,globalx);
+
+ if (globalorientation&64) /* Relative alignment */
+ {
+ dx = mulscale14(wall[wal->point2].x-wal->x,dasqr);
+ dy = mulscale14(wall[wal->point2].y-wal->y,dasqr);
+
+ i = nsqrtasm(daslope*daslope+16777216);
+
+ x = globalx;
+ y = globaly;
+ globalx = dmulscale16(x,dx,y,dy);
+ globaly = mulscale12(dmulscale16(-y,dx,x,dy),i);
+
+ x = ((wal->x-globalposx)<<8);
+ y = ((wal->y-globalposy)<<8);
+ globalx1 = dmulscale16(-x,dx,-y,dy);
+ globaly1 = mulscale12(dmulscale16(-y,dx,x,dy),i);
+
+ x = globalx2;
+ y = globaly2;
+ globalx2 = dmulscale16(x,dx,y,dy);
+ globaly2 = mulscale12(dmulscale16(-y,dx,x,dy),i);
+ }
+ if (globalorientation&0x4)
+ {
+ i = globalx;
+ globalx = -globaly;
+ globaly = -i;
+ i = globalx1;
+ globalx1 = globaly1;
+ globaly1 = i;
+ i = globalx2;
+ globalx2 = -globaly2;
+ globaly2 = -i;
+ }
+ if (globalorientation&0x10) {
+ globalx1 = -globalx1, globalx2 = -globalx2, globalx = -globalx;
+ }
+ if (globalorientation&0x20) {
+ globaly1 = -globaly1, globaly2 = -globaly2, globaly = -globaly;
+ }
+
+ daz = dmulscale9(wx,globalposy-wal->y,-wy,globalposx-wal->x) + ((daz-globalposz)<<8);
+ globalx2 = mulscale20(globalx2,daz);
+ globalx = mulscale28(globalx,daz);
+ globaly2 = mulscale20(globaly2,-daz);
+ globaly = mulscale28(globaly,-daz);
+
+ i = 8-(picsiz[globalpicnum]&15);
+ j = 8-(picsiz[globalpicnum]>>4);
+ if (globalorientation&8) {
+ i++;
+ j++;
+ }
+ globalx1 <<= (i+12);
+ globalx2 <<= i;
+ globalx <<= i;
+ globaly1 <<= (j+12);
+ globaly2 <<= j;
+ globaly <<= j;
+
+ if (dastat == 0)
+ {
+ globalx1 += (((int32_t)sec->ceilingxpanning)<<24);
+ globaly1 += (((int32_t)sec->ceilingypanning)<<24);
+ }
+ else
+ {
+ globalx1 += (((int32_t)sec->floorxpanning)<<24);
+ globaly1 += (((int32_t)sec->floorypanning)<<24);
+ }
+
+ asm1 = -(globalzd>>(16-BITSOFPRECISION));
+
+ globvis = globalvisibility;
+ if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+ globvis = mulscale13(globvis,daz);
+ globvis = mulscale16(globvis,xdimscale);
+ j =(int32_t) FP_OFF(palookup[globalpal]);
+
+ setupslopevlin(((int32_t)(picsiz[globalpicnum]&15))+(((int32_t)(picsiz[globalpicnum]>>4))<<8),tiles[globalpicnum].data,-ylookup[1]);
+
+ l = (globalzd>>16);
+
+ shinc = mulscale16(globalz,xdimenscale);
+ if (shinc > 0)
+ shoffs = (4<<15);
+ else
+ shoffs = ((16380-ydimen)<<15); // JBF: was 2044 16380
+ if (dastat == 0) y1 = umost[dax1];
+ else y1 = max(umost[dax1],dplc[dax1]);
+ m1 = mulscale16(y1,globalzd) + (globalzx>>6);
+ /* Avoid visibility overflow by crossing horizon */
+ if (globalzd > 0) m1 += (globalzd>>16);
+ else m1 -= (globalzd>>16);
+ m2 = m1+l;
+ mptr1 = (int32_t *)&slopalookup[y1+(shoffs>>15)];
+ mptr2 = mptr1+1;
+
+ for(x=dax1; x<=dax2; x++)
+ {
+ if (dastat == 0) {
+ y1 = umost[x];
+ y2 = min(dmost[x],uplc[x])-1;
+ }
+ else {
+ y1 = max(umost[x],dplc[x]);
+ y2 = dmost[x]-1;
+ }
+ if (y1 <= y2)
+ {
+ nptr1 = (int32_t *)&slopalookup[y1+(shoffs>>15)];
+ nptr2 = (int32_t *)&slopalookup[y2+(shoffs>>15)];
+ while (nptr1 <= mptr1)
+ {
+ *mptr1-- = j + (getpalookup((int32_t)mulscale24(krecipasm(m1),globvis),globalshade)<<8);
+ m1 -= l;
+ }
+ while (nptr2 >= mptr2)
+ {
+ *mptr2++ = j + (getpalookup((int32_t)mulscale24(krecipasm(m2),globvis),globalshade)<<8);
+ m2 += l;
+ }
+
+ globalx3 = (globalx2>>10);
+ globaly3 = (globaly2>>10);
+ asm3 = mulscale16(y2,globalzd) + (globalzx>>6);
+ slopevlin(ylookup[y2]+x+frameoffset,krecipasm(asm3>>3),(int32_t)nptr2,y2-y1+1,globalx1,globaly1);
+
+ if ((x&15) == 0) faketimerhandler();
+ }
+ globalx2 += globalx;
+ globaly2 += globaly;
+ globalzx += globalz;
+ shoffs += shinc;
+ }
+}
+
+
+static int owallmost(short *mostbuf, int32_t w, int32_t z)
+{
+ int32_t bad, inty, xcross, y, yinc;
+ int32_t s1, s2, s3, s4, ix1, ix2, iy1, iy2, t;
+
+ z <<= 7;
+ s1 = mulscale20(globaluclip,pvWalls[w].screenSpaceCoo[0][VEC_DIST]);
+ s2 = mulscale20(globaluclip,pvWalls[w].screenSpaceCoo[1][VEC_DIST]);
+ s3 = mulscale20(globaldclip,pvWalls[w].screenSpaceCoo[0][VEC_DIST]);
+ s4 = mulscale20(globaldclip,pvWalls[w].screenSpaceCoo[1][VEC_DIST]);
+ bad = (z<s1)+((z<s2)<<1)+((z>s3)<<2)+((z>s4)<<3);
+
+ ix1 = pvWalls[w].screenSpaceCoo[0][VEC_COL];
+ iy1 = pvWalls[w].screenSpaceCoo[0][VEC_DIST];
+ ix2 = pvWalls[w].screenSpaceCoo[1][VEC_COL];
+ iy2 = pvWalls[w].screenSpaceCoo[1][VEC_DIST];
+
+ if ((bad&3) == 3)
+ {
+ clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),0L);
+ return(bad);
+ }
+
+ if ((bad&12) == 12)
+ {
+ clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
+ return(bad);
+ }
+
+ if (bad&3)
+ {
+ t = divscale30(z-s1,s2-s1);
+ inty = pvWalls[w].screenSpaceCoo[0][VEC_DIST] + mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST]-pvWalls[w].screenSpaceCoo[0][VEC_DIST],t);
+ xcross = pvWalls[w].screenSpaceCoo[0][VEC_COL] + scale(mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST],t),pvWalls[w].screenSpaceCoo[1][VEC_COL]-pvWalls[w].screenSpaceCoo[0][VEC_COL],inty);
+
+ if ((bad&3) == 2)
+ {
+ if (pvWalls[w].screenSpaceCoo[0][VEC_COL] <= xcross) {
+ iy2 = inty;
+ ix2 = xcross;
+ }
+ clearbufbyte(&mostbuf[xcross+1],(pvWalls[w].screenSpaceCoo[1][VEC_COL]-xcross)*sizeof(mostbuf[0]),0L);
+ }
+ else
+ {
+ if (xcross <= pvWalls[w].screenSpaceCoo[1][VEC_COL]) {
+ iy1 = inty;
+ ix1 = xcross;
+ }
+ clearbufbyte(&mostbuf[pvWalls[w].screenSpaceCoo[0][VEC_COL]],(xcross-pvWalls[w].screenSpaceCoo[0][VEC_COL]+1)*sizeof(mostbuf[0]),0L);
+ }
+ }
+
+ if (bad&12)
+ {
+ t = divscale30(z-s3,s4-s3);
+ inty = pvWalls[w].screenSpaceCoo[0][VEC_DIST] + mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST]-pvWalls[w].screenSpaceCoo[0][VEC_DIST],t);
+ xcross = pvWalls[w].screenSpaceCoo[0][VEC_COL] + scale(mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST],t),pvWalls[w].screenSpaceCoo[1][VEC_COL]-pvWalls[w].screenSpaceCoo[0][VEC_COL],inty);
+
+ if ((bad&12) == 8)
+ {
+ if (pvWalls[w].screenSpaceCoo[0][VEC_COL] <= xcross) {
+ iy2 = inty;
+ ix2 = xcross;
+ }
+ clearbufbyte(&mostbuf[xcross+1],(pvWalls[w].screenSpaceCoo[1][VEC_COL]-xcross)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
+ }
+ else
+ {
+ if (xcross <= pvWalls[w].screenSpaceCoo[1][VEC_COL]) {
+ iy1 = inty;
+ ix1 = xcross;
+ }
+ clearbufbyte(&mostbuf[pvWalls[w].screenSpaceCoo[0][VEC_COL]],(xcross-pvWalls[w].screenSpaceCoo[0][VEC_COL]+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
+ }
+ }
+
+ y = (scale(z,xdimenscale,iy1)<<4);
+ yinc = ((scale(z,xdimenscale,iy2)<<4)-y) / (ix2-ix1+1);
+ qinterpolatedown16short((int32_t *)&mostbuf[ix1],ix2-ix1+1,y+(globalhoriz<<16),yinc);
+
+ if (mostbuf[ix1] < 0) mostbuf[ix1] = 0;
+ if (mostbuf[ix1] > ydimen) mostbuf[ix1] = ydimen;
+ if (mostbuf[ix2] < 0) mostbuf[ix2] = 0;
+ if (mostbuf[ix2] > ydimen) mostbuf[ix2] = ydimen;
+
+ return(bad);
+}
+
+
+static int wallmost(short *mostbuf, int32_t w, int32_t sectnum, uint8_t dastat)
+{
+ int32_t bad, i, j, t, y, z, inty, intz, xcross, yinc, fw;
+ int32_t x1, y1, z1, x2, y2, z2, xv, yv, dx, dy, dasqr, oz1, oz2;
+ int32_t s1, s2, s3, s4, ix1, ix2, iy1, iy2;
+
+ if (dastat == 0){
+ z = sector[sectnum].ceilingz-globalposz;
+ if ((sector[sectnum].ceilingstat&2) == 0)
+ return(owallmost(mostbuf,w,z));
+ }
+ else{
+ z = sector[sectnum].floorz-globalposz;
+ if ((sector[sectnum].floorstat&2) == 0)
+ return(owallmost(mostbuf,w,z));
+ }
+
+ i = pvWalls[w].worldWallId;
+ if (i == sector[sectnum].wallptr)
+ return(owallmost(mostbuf,w,z));
+
+ x1 = wall[i].x;
+ x2 = wall[wall[i].point2].x-x1;
+ y1 = wall[i].y;
+ y2 = wall[wall[i].point2].y-y1;
+
+ fw = sector[sectnum].wallptr;
+ i = wall[fw].point2;
+ dx = wall[i].x-wall[fw].x;
+ dy = wall[i].y-wall[fw].y;
+ dasqr = krecipasm(nsqrtasm(dx*dx+dy*dy));
+
+ if (pvWalls[w].screenSpaceCoo[0][VEC_COL] == 0){
+ xv = cosglobalang+sinviewingrangeglobalang;
+ yv = singlobalang-cosviewingrangeglobalang;
+ }
+ else{
+ xv = x1-globalposx;
+ yv = y1-globalposy;
+ }
+ i = xv*(y1-globalposy)-yv*(x1-globalposx);
+ j = yv*x2-xv*y2;
+
+ if (klabs(j) > klabs(i>>3))
+ i = divscale28(i,j);
+
+ if (dastat == 0){
+ t = mulscale15(sector[sectnum].ceilingheinum,dasqr);
+ z1 = sector[sectnum].ceilingz;
+ }
+ else{
+ t = mulscale15(sector[sectnum].floorheinum,dasqr);
+ z1 = sector[sectnum].floorz;
+ }
+
+ z1 = dmulscale24(dx*t,mulscale20(y2,i)+((y1-wall[fw].y)<<8),-dy*t,mulscale20(x2,i)+((x1-wall[fw].x)<<8))+((z1-globalposz)<<7);
+
+
+ if (pvWalls[w].screenSpaceCoo[1][VEC_COL] == xdimen-1){
+ xv = cosglobalang-sinviewingrangeglobalang;
+ yv = singlobalang+cosviewingrangeglobalang;
+ }
+ else{
+ xv = (x2+x1)-globalposx;
+ yv = (y2+y1)-globalposy;
+ }
+
+ i = xv*(y1-globalposy)-yv*(x1-globalposx);
+ j = yv*x2-xv*y2;
+
+ if (klabs(j) > klabs(i>>3))
+ i = divscale28(i,j);
+
+ if (dastat == 0){
+ t = mulscale15(sector[sectnum].ceilingheinum,dasqr);
+ z2 = sector[sectnum].ceilingz;
+ }
+ else{
+ t = mulscale15(sector[sectnum].floorheinum,dasqr);
+ z2 = sector[sectnum].floorz;
+ }
+
+ z2 = dmulscale24(dx*t,mulscale20(y2,i)+((y1-wall[fw].y)<<8),-dy*t,mulscale20(x2,i)+((x1-wall[fw].x)<<8))+((z2-globalposz)<<7);
+
+
+ s1 = mulscale20(globaluclip,pvWalls[w].screenSpaceCoo[0][VEC_DIST]);
+ s2 = mulscale20(globaluclip,pvWalls[w].screenSpaceCoo[1][VEC_DIST]);
+ s3 = mulscale20(globaldclip,pvWalls[w].screenSpaceCoo[0][VEC_DIST]);
+ s4 = mulscale20(globaldclip,pvWalls[w].screenSpaceCoo[1][VEC_DIST]);
+ bad = (z1<s1)+((z2<s2)<<1)+((z1>s3)<<2)+((z2>s4)<<3);
+
+ ix1 = pvWalls[w].screenSpaceCoo[0][VEC_COL];
+ ix2 = pvWalls[w].screenSpaceCoo[1][VEC_COL];
+ iy1 = pvWalls[w].screenSpaceCoo[0][VEC_DIST];
+ iy2 = pvWalls[w].screenSpaceCoo[1][VEC_DIST];
+ oz1 = z1;
+ oz2 = z2;
+
+ if ((bad&3) == 3){
+ clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),0L);
+ return(bad);
+ }
+
+ if ((bad&12) == 12){
+ clearbufbyte(&mostbuf[ix1],(ix2-ix1+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
+ return(bad);
+ }
+
+ if (bad&3){
+ /* inty = intz / (globaluclip>>16) */
+ t = divscale30(oz1-s1,s2-s1+oz1-oz2);
+ inty = pvWalls[w].screenSpaceCoo[0][VEC_DIST] + mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST]-pvWalls[w].screenSpaceCoo[0][VEC_DIST],t);
+ intz = oz1 + mulscale30(oz2-oz1,t);
+ xcross = pvWalls[w].screenSpaceCoo[0][VEC_COL] + scale(mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST],t),pvWalls[w].screenSpaceCoo[1][VEC_COL]-pvWalls[w].screenSpaceCoo[0][VEC_COL],inty);
+
+ if ((bad&3) == 2){
+ if (pvWalls[w].screenSpaceCoo[0][VEC_COL] <= xcross){
+ z2 = intz;
+ iy2 = inty;
+ ix2 = xcross;
+ }
+ clearbufbyte(&mostbuf[xcross+1],(pvWalls[w].screenSpaceCoo[1][VEC_COL]-xcross)*sizeof(mostbuf[0]),0L);
+ }
+ else{
+ if (xcross <= pvWalls[w].screenSpaceCoo[1][VEC_COL]) {
+ z1 = intz;
+ iy1 = inty;
+ ix1 = xcross;
+ }
+ clearbufbyte(&mostbuf[pvWalls[w].screenSpaceCoo[0][VEC_COL]],(xcross-pvWalls[w].screenSpaceCoo[0][VEC_COL]+1)*sizeof(mostbuf[0]),0L);
+ }
+ }
+
+ if (bad&12){
+ /* inty = intz / (globaldclip>>16) */
+ t = divscale30(oz1-s3,s4-s3+oz1-oz2);
+ inty = pvWalls[w].screenSpaceCoo[0][VEC_DIST] + mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST]-pvWalls[w].screenSpaceCoo[0][VEC_DIST],t);
+ intz = oz1 + mulscale30(oz2-oz1,t);
+ xcross = pvWalls[w].screenSpaceCoo[0][VEC_COL] + scale(mulscale30(pvWalls[w].screenSpaceCoo[1][VEC_DIST],t),pvWalls[w].screenSpaceCoo[1][VEC_COL]-pvWalls[w].screenSpaceCoo[0][VEC_COL],inty);
+
+ if ((bad&12) == 8){
+ if (pvWalls[w].screenSpaceCoo[0][VEC_COL] <= xcross) {
+ z2 = intz;
+ iy2 = inty;
+ ix2 = xcross;
+ }
+ clearbufbyte(&mostbuf[xcross+1],(pvWalls[w].screenSpaceCoo[1][VEC_COL]-xcross)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
+ }
+ else{
+ if (xcross <= pvWalls[w].screenSpaceCoo[1][VEC_COL]) {
+ z1 = intz;
+ iy1 = inty;
+ ix1 = xcross;
+ }
+ clearbufbyte(&mostbuf[pvWalls[w].screenSpaceCoo[0][VEC_COL]],(xcross-pvWalls[w].screenSpaceCoo[0][VEC_COL]+1)*sizeof(mostbuf[0]),ydimen+(ydimen<<16));
+ }
+ }
+
+ y = (scale(z1,xdimenscale,iy1)<<4);
+ yinc = ((scale(z2,xdimenscale,iy2)<<4)-y) / (ix2-ix1+1);
+ qinterpolatedown16short((int32_t *)&mostbuf[ix1],ix2-ix1+1,y+(globalhoriz<<16),yinc);
+
+ if (mostbuf[ix1] < 0)
+ mostbuf[ix1] = 0;
+ if (mostbuf[ix1] > ydimen)
+ mostbuf[ix1] = ydimen;
+ if (mostbuf[ix2] < 0)
+ mostbuf[ix2] = 0;
+ if (mostbuf[ix2] > ydimen)
+ mostbuf[ix2] = ydimen;
+
+ return(bad);
+}
+
+
+static void drawalls(int32_t bunch)
+{
+ sectortype *sec, *nextsec;
+ walltype *wal;
+ int32_t i, x, x1, x2, cz[5], fz[5];
+ int32_t z, wallnum, sectnum, nextsectnum;
+ int32_t startsmostwallcnt, startsmostcnt, gotswall;
+ uint8_t andwstat1, andwstat2;
+
+ z = bunchfirst[bunch];
+ sectnum = pvWalls[z].sectorId;
+ sec = &sector[sectnum];
+
+ andwstat1 = 0xff;
+ andwstat2 = 0xff;
+ for(; z>=0; z=bunchWallsList[z]){ /* uplc/dplc calculation */
+
+ andwstat1 &= wallmost(uplc,z,sectnum,(uint8_t )0);
+ andwstat2 &= wallmost(dplc,z,sectnum,(uint8_t )1);
+ }
+
+ /* draw ceilings */
+ if ((andwstat1&3) != 3){
+ if ((sec->ceilingstat&3) == 2)
+ grouscan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum,0);
+ else if ((sec->ceilingstat&1) == 0)
+ ceilscan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum);
+ else
+ parascan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum,0,bunch);
+ }
+
+ /* draw floors */
+ if ((andwstat2&12) != 12){
+ if ((sec->floorstat&3) == 2)
+ grouscan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum,1);
+ else if ((sec->floorstat&1) == 0)
+ florscan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum);
+ else
+ parascan(pvWalls[bunchfirst[bunch]].screenSpaceCoo[0][VEC_COL],pvWalls[bunchlast[bunch]].screenSpaceCoo[1][VEC_COL],sectnum,1,bunch);
+ }
+
+ /* DRAW WALLS SECTION! */
+ for(z=bunchfirst[bunch]; z>=0; z=bunchWallsList[z]){
+
+ x1 = pvWalls[z].screenSpaceCoo[0][VEC_COL];
+ x2 = pvWalls[z].screenSpaceCoo[1][VEC_COL];
+ if (umost[x2] >= dmost[x2])
+ {
+
+ for(x=x1; x<x2; x++)
+ if (umost[x] < dmost[x])
+ break;
+
+ if (x >= x2)
+ {
+ smostwall[smostwallcnt] = z;
+ smostwalltype[smostwallcnt] = 0;
+ smostwallcnt++;
+ continue;
+ }
+ }
+
+ wallnum = pvWalls[z].worldWallId;
+ wal = &wall[wallnum];
+ nextsectnum = wal->nextsector;
+ nextsec = &sector[nextsectnum];
+
+ gotswall = 0;
+
+ startsmostwallcnt = smostwallcnt;
+ startsmostcnt = smostcnt;
+
+ if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
+ {
+ if (searchy <= uplc[searchx]){ /* ceiling */
+ searchsector = sectnum;
+ searchwall = wallnum;
+ searchstat = 1;
+ searchit = 1;
+ }
+ else if (searchy >= dplc[searchx]){ /* floor */
+ searchsector = sectnum;
+ searchwall = wallnum;
+ searchstat = 2;
+ searchit = 1;
+ }
+ }
+
+ if (nextsectnum >= 0){
+ getzsofslope((short)sectnum,wal->x,wal->y,&cz[0],&fz[0]);
+ getzsofslope((short)sectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[1],&fz[1]);
+ getzsofslope((short)nextsectnum,wal->x,wal->y,&cz[2],&fz[2]);
+ getzsofslope((short)nextsectnum,wall[wal->point2].x,wall[wal->point2].y,&cz[3],&fz[3]);
+ getzsofslope((short)nextsectnum,globalposx,globalposy,&cz[4],&fz[4]);
+
+ if ((wal->cstat&48) == 16)
+ maskwall[maskwallcnt++] = z;
+
+ if (((sec->ceilingstat&1) == 0) || ((nextsec->ceilingstat&1) == 0)){
+ if ((cz[2] <= cz[0]) && (cz[3] <= cz[1])){
+ if (globparaceilclip)
+ for(x=x1; x<=x2; x++)
+ if (uplc[x] > umost[x])
+ if (umost[x] <= dmost[x]){
+ umost[x] = uplc[x];
+ if (umost[x] > dmost[x]) numhits--;
+ }
+ }
+ else{
+ wallmost(dwall,z,nextsectnum,(uint8_t )0);
+ if ((cz[2] > fz[0]) || (cz[3] > fz[1]))
+ for(i=x1; i<=x2; i++) if (dwall[i] > dplc[i]) dwall[i] = dplc[i];
+
+ if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
+ if (searchy <= dwall[searchx]) /* wall */{
+ searchsector = sectnum;
+ searchwall = wallnum;
+ searchstat = 0;
+ searchit = 1;
+ }
+
+ globalorientation = (int32_t)wal->cstat;
+ globalpicnum = wal->picnum;
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
+ globalxpanning = (int32_t)wal->xpanning;
+ globalypanning = (int32_t)wal->ypanning;
+ globalshiftval = (picsiz[globalpicnum]>>4);
+ if (pow2long[globalshiftval] != tiles[globalpicnum].dim.height) globalshiftval++;
+ globalshiftval = 32-globalshiftval;
+
+ //Animated
+ if (tiles[globalpicnum].animFlags&192)
+ globalpicnum += animateoffs(globalpicnum);
+
+ globalshade = (int32_t)wal->shade;
+ globvis = globalvisibility;
+ if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+ globalpal = (int32_t)wal->pal;
+ globalyscale = (wal->yrepeat<<(globalshiftval-19));
+ if ((globalorientation&4) == 0)
+ globalzd = (((globalposz-nextsec->ceilingz)*globalyscale)<<8);
+ else
+ globalzd = (((globalposz-sec->ceilingz)*globalyscale)<<8);
+ globalzd += (globalypanning<<24);
+ if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
+
+ if (gotswall == 0) {
+ gotswall = 1;
+ prepwall(z,wal);
+ }
+ wallscan(x1,x2,uplc,dwall,swall,lwall);
+
+ if ((cz[2] >= cz[0]) && (cz[3] >= cz[1])){
+ for(x=x1; x<=x2; x++)
+ if (dwall[x] > umost[x])
+ if (umost[x] <= dmost[x]){
+ umost[x] = dwall[x];
+ if (umost[x] > dmost[x]) numhits--;
+ }
+ }
+ else
+ {
+ for(x=x1; x<=x2; x++)
+ if (umost[x] <= dmost[x]){
+ i = max(uplc[x],dwall[x]);
+ if (i > umost[x]){
+ umost[x] = i;
+ if (umost[x] > dmost[x]) numhits--;
+ }
+ }
+ }
+ }
+ if ((cz[2] < cz[0]) || (cz[3] < cz[1]) || (globalposz < cz[4])){
+ i = x2-x1+1;
+ if (smostcnt+i < MAXYSAVES){
+ smoststart[smostwallcnt] = smostcnt;
+ smostwall[smostwallcnt] = z;
+ smostwalltype[smostwallcnt] = 1; /* 1 for umost */
+ smostwallcnt++;
+ copybufbyte((int32_t *)&umost[x1],(int32_t *)&smost[smostcnt],i*sizeof(smost[0]));
+ smostcnt += i;
+ }
+ }
+ }
+ if (((sec->floorstat&1) == 0) || ((nextsec->floorstat&1) == 0)){
+ if ((fz[2] >= fz[0]) && (fz[3] >= fz[1])){
+ if (globparaflorclip)
+ for(x=x1; x<=x2; x++)
+ if (dplc[x] < dmost[x])
+ if (umost[x] <= dmost[x]){
+ dmost[x] = dplc[x];
+ if (umost[x] > dmost[x]) numhits--;
+ }
+ }
+ else{
+ wallmost(uwall,z,nextsectnum,(uint8_t )1);
+ if ((fz[2] < cz[0]) || (fz[3] < cz[1]))
+ for(i=x1; i<=x2; i++) if (uwall[i] < uplc[i]) uwall[i] = uplc[i];
+
+ if ((searchit == 2) && (searchx >= x1) && (searchx <= x2))
+ if (searchy >= uwall[searchx]) /* wall */{
+ searchsector = sectnum;
+ searchwall = wallnum;
+ if ((wal->cstat&2) > 0) searchwall = wal->nextwall;
+ searchstat = 0;
+ searchit = 1;
+ }
+
+ if ((wal->cstat&2) > 0){
+ wallnum = wal->nextwall;
+ wal = &wall[wallnum];
+ globalorientation = (int32_t)wal->cstat;
+ globalpicnum = wal->picnum;
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
+ globalxpanning = (int32_t)wal->xpanning;
+ globalypanning = (int32_t)wal->ypanning;
+
+ if (tiles[globalpicnum].animFlags&192)
+ globalpicnum += animateoffs(globalpicnum);
+
+ globalshade = (int32_t)wal->shade;
+ globalpal = (int32_t)wal->pal;
+ wallnum = pvWalls[z].worldWallId;
+ wal = &wall[wallnum];
+ }
+ else{
+ globalorientation = (int32_t)wal->cstat;
+ globalpicnum = wal->picnum;
+
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
+ globalpicnum = 0;
+
+ globalxpanning = (int32_t)wal->xpanning;
+ globalypanning = (int32_t)wal->ypanning;
+
+ if (tiles[globalpicnum].animFlags&192)
+ globalpicnum += animateoffs(globalpicnum);
+ globalshade = (int32_t)wal->shade;
+ globalpal = (int32_t)wal->pal;
+ }
+ globvis = globalvisibility;
+ if (sec->visibility != 0)
+ globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+ globalshiftval = (picsiz[globalpicnum]>>4);
+
+ if (pow2long[globalshiftval] != tiles[globalpicnum].dim.height)
+ globalshiftval++;
+
+ globalshiftval = 32-globalshiftval;
+ globalyscale = (wal->yrepeat<<(globalshiftval-19));
+
+ if ((globalorientation&4) == 0)
+ globalzd = (((globalposz-nextsec->floorz)*globalyscale)<<8);
+ else
+ globalzd = (((globalposz-sec->ceilingz)*globalyscale)<<8);
+
+ globalzd += (globalypanning<<24);
+ if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
+
+ if (gotswall == 0) {
+ gotswall = 1;
+ prepwall(z,wal);
+ }
+ wallscan(x1,x2,uwall,dplc,swall,lwall);
+
+ if ((fz[2] <= fz[0]) && (fz[3] <= fz[1]))
+ {
+ for(x=x1; x<=x2; x++)
+ if (uwall[x] < dmost[x])
+ if (umost[x] <= dmost[x]){
+ dmost[x] = uwall[x];
+ if (umost[x] > dmost[x]) numhits--;
+ }
+ }
+ else
+ {
+ for(x=x1; x<=x2; x++)
+ if (umost[x] <= dmost[x]){
+ i = min(dplc[x],uwall[x]);
+ if (i < dmost[x])
+ {
+ dmost[x] = i;
+ if (umost[x] > dmost[x]) numhits--;
+ }
+ }
+ }
+ }
+ if ((fz[2] > fz[0]) || (fz[3] > fz[1]) || (globalposz > fz[4])){
+ i = x2-x1+1;
+ if (smostcnt+i < MAXYSAVES){
+ smoststart[smostwallcnt] = smostcnt;
+ smostwall[smostwallcnt] = z;
+ smostwalltype[smostwallcnt] = 2; /* 2 for dmost */
+ smostwallcnt++;
+ copybufbyte((int32_t *)&dmost[x1],(int32_t *)&smost[smostcnt],i*sizeof(smost[0]));
+ smostcnt += i;
+ }
+ }
+ }
+ if (numhits < 0) return;
+ if ((!(wal->cstat&32)) && ((visitedSectors[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)){
+ if (umost[x2] < dmost[x2])
+ scansector((short) nextsectnum);
+ else
+ {
+ for(x=x1; x<x2; x++)
+ if (umost[x] < dmost[x]){
+ scansector((short) nextsectnum);
+ break;
+ }
+
+ /*
+ * If can't see sector beyond, then cancel smost array and just
+ * store wall!
+ */
+ if (x == x2){
+ smostwallcnt = startsmostwallcnt;
+ smostcnt = startsmostcnt;
+ smostwall[smostwallcnt] = z;
+ smostwalltype[smostwallcnt] = 0;
+ smostwallcnt++;
+ }
+ }
+ }
+ }
+ if ((nextsectnum < 0) || (wal->cstat&32)) /* White/1-way wall */
+ {
+ globalorientation = (int32_t)wal->cstat;
+ if (nextsectnum < 0)
+ globalpicnum = wal->picnum;
+ else
+ globalpicnum = wal->overpicnum;
+
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
+ globalpicnum = 0;
+
+ globalxpanning = (int32_t)wal->xpanning;
+ globalypanning = (int32_t)wal->ypanning;
+
+ if (tiles[globalpicnum].animFlags&192)
+ globalpicnum += animateoffs(globalpicnum);
+
+ globalshade = (int32_t)wal->shade;
+ globvis = globalvisibility;
+ if (sec->visibility != 0)
+ globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+
+ globalpal = (int32_t)wal->pal;
+ globalshiftval = (picsiz[globalpicnum]>>4);
+ if (pow2long[globalshiftval] != tiles[globalpicnum].dim.height)
+ globalshiftval++;
+
+ globalshiftval = 32-globalshiftval;
+ globalyscale = (wal->yrepeat<<(globalshiftval-19));
+ if (nextsectnum >= 0)
+ {
+ if ((globalorientation&4) == 0)
+ globalzd = globalposz-nextsec->ceilingz;
+ else
+ globalzd = globalposz-sec->ceilingz;
+ }
+ else
+ {
+ if ((globalorientation&4) == 0)
+ globalzd = globalposz-sec->ceilingz;
+ else
+ globalzd = globalposz-sec->floorz;
+ }
+ globalzd = ((globalzd*globalyscale)<<8) + (globalypanning<<24);
+
+ if (globalorientation&256){
+ globalyscale = -globalyscale;
+ globalzd = -globalzd;
+ }
+
+ if (gotswall == 0) {
+ gotswall = 1;
+ prepwall(z,wal);
+ }
+
+ wallscan(x1,x2,uplc,dplc,swall,lwall);
+
+ for(x=x1; x<=x2; x++)
+ if (umost[x] <= dmost[x])
+ {
+ umost[x] = 1;
+ dmost[x] = 0;
+ numhits--;
+ }
+ smostwall[smostwallcnt] = z;
+ smostwalltype[smostwallcnt] = 0;
+ smostwallcnt++;
+
+ if ((searchit == 2) && (searchx >= x1) && (searchx <= x2)){
+ searchit = 1;
+ searchsector = sectnum;
+ searchwall = wallnum;
+ if (nextsectnum < 0) searchstat = 0;
+ else searchstat = 4;
+ }
+ }
+ }
+}
+
+
+static void dosetaspect(void)
+{
+ int32_t i, j, k, x, xinc;
+
+ if (xyaspect != oxyaspect){
+ oxyaspect = xyaspect;
+ j = xyaspect*320;
+ horizlookup2[horizycent-1] = divscale26(131072,j);
+ for(i=ydim*4-1; i>=0; i--)
+ if (i != (horizycent-1)){
+ horizlookup[i] = divscale28(1,i-(horizycent-1));
+ horizlookup2[i] = divscale14(klabs(horizlookup[i]),j);
+ }
+ }
+
+
+ if ((xdimen != oxdimen) || (viewingrange != oviewingrange)){
+ oxdimen = xdimen;
+ oviewingrange = viewingrange;
+ xinc = mulscale32(viewingrange*320,xdimenrecip);
+ x = (640<<16)-mulscale1(xinc,xdimen);
+ for(i=0; i<xdimen; i++){
+ j = (x&65535);
+ k = (x>>16);
+ x += xinc;
+ if (j != 0) j = mulscale16((int32_t)radarang[k+1]-(int32_t)radarang[k],j);
+ radarang2[i] = (short)(((int32_t)radarang[k]+j)>>6);
+ }
+ }
+}
+
+
+/*
+ FCS: Geez one more horrible algorithm to decipher :| :/ :( cry smiley.....
+ Algorithm:
+
+ 1.
+ Take wall 1 vector [point1,point2] and using two cross products determine if the two endpoints of wall 2 are on the same side of Wall 1 plan.
+ If they are then we can determine according to globalposx and globalposy if wall2 is before or after wall1's plan.
+
+ 2. Do the same thing again but this time with wall2's plan. Try to find if wall1 is in front of behind wall2's plan.
+
+ Key concept: If a cross-product is equal to 0 this mean they are parallel.
+
+ Return: pvWallID1 in the potentially visible wall list is in front of pvWallID2 (in the same potentially visible list)
+*/
+int wallfront(int32_t pvWallID1, int32_t pvWallID2)
+{
+ walltype *wal;
+ int32_t x11, y11, x21, y21, x12, y12, x22, y22, dx, dy, t1, t2;
+
+ //It seems we are going to work in Worldspace coordinates.
+ wal = &wall[pvWalls[pvWallID1].worldWallId];
+ x11 = wal->x;
+ y11 = wal->y;
+ wal = &wall[wal->point2];
+ x21 = wal->x;
+ y21 = wal->y;
+ wal = &wall[pvWalls[pvWallID2].worldWallId];
+ x12 = wal->x;
+ y12 = wal->y;
+ wal = &wall[wal->point2];
+ x22 = wal->x;
+ y22 = wal->y;
+
+
+ //This is part 1
+
+ //Wall 1's vector
+ dx = x21-x11;
+ dy = y21-y11;
+
+ //This is a cross-product between Wall 1 vector and the [Wall 1 Point 1-> Wall 2 Point 1] vector
+ t1 = dmulscale2(x12-x11,dy,-dx,y12-y11); /* p1(l2) vs. l1 */
+ //This is a cross-product between Wall 1 vector and the [Wall 1 Point 1-> Wall 2 Point 2] vector
+ t2 = dmulscale2(x22-x11,dy,-dx,y22-y11); /* p2(l2) vs. l1 */
+
+ //If the vectors a parallel, then the cross-product is zero.
+ if (t1 == 0) {
+ //wall2's point1 is on wall1's plan.
+ t1 = t2;
+ if (t1 == 0) // Those two walls are on the same plan.
+ {
+ //Wall 2's point 2 is on wall1's plan.
+ return(-1);
+ }
+ }
+ if (t2 == 0)
+ t2 = t1;
+
+
+ //This XOR just determine if the cross-product have the same sign and hence if both points are on the same side of wall 1 plan.
+ //Test if both points of wall2 are on the same side of wall 1 (in front or behind).
+ if ((t1^t2) >= 0)
+ {
+ //cross-product have the same sign: Both points of wall2 are on the same side of wall1 : An answer is possible !!
+
+ //Now is time to take into account the camera position and determine which of wall1 or wall2 is seen first.
+ t2 = dmulscale2(globalposx-x11,dy,-dx,globalposy-y11); /* pos vs. l1 */
+
+ //Test the cross product sign difference.
+ //If (t2^t1) >= 0 then both cross product had different sign so wall1 is in front of wall2
+ //otherwise wall2 is in front of wall1
+ return((t2^t1) >= 0);
+ }
+
+
+ //This is part 2
+ //Do it again but this time will wall2's plan.
+
+ //Wall 2's vector
+ dx = x22-x12;
+ dy = y22-y12;
+
+ t1 = dmulscale2(x11-x12,dy,-dx,y11-y12); /* p1(l1) vs. l2 */
+ t2 = dmulscale2(x21-x12,dy,-dx,y21-y12); /* p2(l1) vs. l2 */
+ if (t1 == 0) {
+ t1 = t2;
+ if (t1 == 0)
+ return(-1);
+ }
+ if (t2 == 0)
+ t2 = t1;
+ if ((t1^t2) >= 0)
+ {
+ t2 = dmulscale2(globalposx-x12,dy,-dx,globalposy-y12); /* pos vs. l2 */
+ return((t2^t1) < 0);
+ }
+
+ //FCS: No wall is in front of the other's plan: This means they are crossing.
+ return(-2);
+}
+
+
+//Return 1 if bunch firstBunchID is in from of bunch secondBunchID.
+static int bunchfront(int32_t firstBunchID, int32_t secondBunchID)
+{
+ int32_t x1b1, x2b1, x1b2, x2b2;
+
+
+ x1b1 = pvWalls[bunchfirst[firstBunchID]].screenSpaceCoo[0][VEC_COL];
+ x2b2 = pvWalls[bunchlast[secondBunchID]].screenSpaceCoo[1][VEC_COL]+1;
+ if (x1b1 >= x2b2)
+ {
+ //Bunch 1 left side is completely on the right of bunch2's right in screenspace: They do not overlap.
+ return(-1);
+ }
+
+
+ x1b2 = pvWalls[bunchfirst[secondBunchID]].screenSpaceCoo[0][VEC_COL];
+ x2b1 = pvWalls[bunchlast[firstBunchID]].screenSpaceCoo[1][VEC_COL]+1;
+ if (x1b2 >= x2b1)
+ {
+ //Bunch 2 left side is completely on the right of bunch 1 right side: They do not overlap.
+ return(-1);
+ }
+
+
+ if (x1b1 >= x1b2)
+ {
+ //Get the last wall in the bunch2.
+ int lastWallID;
+ for(lastWallID=bunchfirst[secondBunchID];
+ pvWalls[lastWallID].screenSpaceCoo[1][VEC_COL]<x1b1;
+ lastWallID=bunchWallsList[lastWallID]);
+
+ return(wallfront(bunchfirst[firstBunchID],lastWallID));
+ }
+ else
+ {
+ //Get the last wall in the bunch.
+ int lastWallID;
+ for(lastWallID=bunchfirst[firstBunchID];
+ pvWalls[lastWallID].screenSpaceCoo[1][VEC_COL]<x1b2;
+ lastWallID=bunchWallsList[lastWallID]);
+
+ return(wallfront(lastWallID,bunchfirst[secondBunchID]));
+ }
+}
+
+int pixelRenderable = 0;
+//#include "keyboard.h"
+//void WriteLastPaletteToFile(void);
+//void WriteTranslucToFile(void);
+/*
+ FCS: Draw every walls in Front to Back Order.
+*/
+void drawrooms(int32_t daposx, int32_t daposy, int32_t daposz,short daang, int32_t dahoriz, short dacursectnum)
+{
+ int32_t i, j, z, closest;
+ //Ceiling and Floor height at the player position.
+ int32_t cz, fz;
+ short *shortptr1, *shortptr2;
+
+ // When visualizing the rendering process, part of the screen
+ // are not updated: In order to avoid the "ghost effect", we
+ // clear the framebuffer to black.
+ if (CLEAR_FRAMEBUFFER)
+ clear2dscreen();
+
+
+ //CODE EXPLORATION
+ /*
+ if( KB_KeyDown[0x39]){ // 0x39 = SPACE
+ //CODE EXPLORATION
+ WriteLastPaletteToFile();
+ WriteTranslucToFile();
+ }
+ */
+
+ pixelRenderable+=100;
+ if (pixelRenderable >= MAX_PIXEL_RENDERERED)
+ pixelRenderable = 0 ;
+
+ //pixelsAllowed = pixelRenderable;
+ pixelsAllowed = 100000000;
+ //printf("%d\n",pixelsAllowed);
+
+ beforedrawrooms = 0;
+
+ // FCS: What was the point of having those values as parameters of this function....if it is to overwrite the
+ // values with the gloval variables ?!?!?
+ globalposx = daposx;
+ globalposy = daposy;
+ globalposz = daposz;
+ globalang = (daang&2047); //FCS: Mask and keep only 11 bits of angle value.
+
+ globalhoriz = mulscale16(dahoriz-100,xdimenscale)+(ydimen>>1);
+ globaluclip = (0-globalhoriz)*xdimscale;
+ globaldclip = (ydimen-globalhoriz)*xdimscale;
+
+ i = mulscale16(xdimenscale,viewingrangerecip);
+ globalpisibility = mulscale16(parallaxvisibility,i);
+ globalvisibility = mulscale16(visibility,i);
+ globalhisibility = mulscale16(globalvisibility,xyaspect);
+ globalcisibility = mulscale8(globalhisibility,320);
+
+ globalcursectnum = dacursectnum;
+ totalclocklock = totalclock;
+
+ cosglobalang = sintable[(globalang+512)&2047];
+ singlobalang = sintable[globalang&2047];
+ cosviewingrangeglobalang = mulscale16(cosglobalang,viewingrange);
+ sinviewingrangeglobalang = mulscale16(singlobalang,viewingrange);
+
+ if (stereomode != 0)
+ {
+ if (stereopixelwidth != ostereopixelwidth)
+ {
+ ostereopixelwidth = stereopixelwidth;
+ xdimen = (windowx2-windowx1+1)+(stereopixelwidth<<1);
+ halfxdimen = (xdimen>>1);
+ xdimenrecip = divscale32(1L,xdimen);
+ setaspect((int32_t)divscale16(xdimen,windowx2-windowx1+1),yxaspect);
+ }
+
+ if ((!(activepage&1)) ^ inpreparemirror)
+ {
+ for(i=windowx1; i<windowx1+(stereopixelwidth<<1); i++) {
+ startumost[i] = 1, startdmost[i] = 0;
+ }
+ for(; i<windowx2+1+(stereopixelwidth<<1); i++) {
+ startumost[i] = windowy1, startdmost[i] = windowy2+1;
+ }
+ viewoffset = windowy1*bytesperline+windowx1-(stereopixelwidth<<1);
+ i = stereowidth;
+ }
+ else
+ {
+ for(i=windowx1; i<windowx2+1; i++) {
+ startumost[i] = windowy1, startdmost[i] = windowy2+1;
+ }
+ for(; i<windowx2+1+(stereopixelwidth<<1); i++) {
+ startumost[i] = 1, startdmost[i] = 0;
+ }
+ viewoffset = windowy1*bytesperline+windowx1;
+ i = -stereowidth;
+ }
+ globalposx += mulscale24(singlobalang,i);
+ globalposy -= mulscale24(cosglobalang,i);
+
+ }
+
+ if ((xyaspect != oxyaspect) || (xdimen != oxdimen) || (viewingrange != oviewingrange))
+ dosetaspect();
+
+ frameoffset = frameplace+viewoffset;
+
+ //Clear the bit vector that keep track of what sector has been flooded in.
+ clearbufbyte(visitedSectors,(int32_t)((numsectors+7)>>3),0L);
+
+ //Clear the occlusion array.
+ shortptr1 = (short *)&startumost[windowx1];
+ shortptr2 = (short *)&startdmost[windowx1];
+ i = xdimen-1;
+ do
+ {
+ umost[i] = shortptr1[i]-windowy1;
+ dmost[i] = shortptr2[i]-windowy1;
+ i--;
+ } while (i != 0);
+ umost[0] = shortptr1[0]-windowy1;
+ dmost[0] = shortptr2[0]-windowy1;
+
+ //NumHits is the number of column to draw.
+ numhits = xdimen;
+ //Num walls to potentially render.
+ numscans = 0;
+
+ numbunches = 0;
+ maskwallcnt = 0;
+ smostwallcnt = 0;
+ smostcnt = 0;
+ spritesortcnt = 0;
+
+ if (globalcursectnum >= MAXSECTORS)
+ globalcursectnum -= MAXSECTORS;
+ else
+ {
+ // Even if the player leaves the map, the engine will keep on rendering from the last visited sector.
+ // Save it.
+ i = globalcursectnum;
+ updatesector(globalposx,globalposy,&globalcursectnum);
+ //Seem the player has left the map since updatesector cannot locate him -> Restore to the last known sector.
+ if (globalcursectnum < 0)
+ globalcursectnum = i;
+ }
+
+ globparaceilclip = 1;
+ globparaflorclip = 1;
+
+ //Update the ceiling and floor Z coordinate for the player's 2D position.
+ getzsofslope(globalcursectnum,globalposx,globalposy,&cz,&fz);
+
+ if (globalposz < cz) globparaceilclip = 0;
+ if (globalposz > fz) globparaflorclip = 0;
+
+ //Build the list of potentially visible wall in to "bunches".
+ scansector(globalcursectnum);
+
+ if (inpreparemirror)
+ {
+ inpreparemirror = 0;
+ mirrorsx1 = xdimen-1;
+ mirrorsx2 = 0;
+ for(i=numscans-1; i>=0; i--)
+ {
+ if (wall[pvWalls[i].worldWallId].nextsector < 0) continue;
+ if (pvWalls[i].screenSpaceCoo[0][VEC_COL] < mirrorsx1) mirrorsx1 = pvWalls[i].screenSpaceCoo[0][VEC_COL];
+ if (pvWalls[i].screenSpaceCoo[1][VEC_COL] > mirrorsx2) mirrorsx2 = pvWalls[i].screenSpaceCoo[1][VEC_COL];
+ }
+
+ if (stereomode)
+ {
+ mirrorsx1 += (stereopixelwidth<<1);
+ mirrorsx2 += (stereopixelwidth<<1);
+ }
+
+ for(i=0; i<mirrorsx1; i++)
+ if (umost[i] <= dmost[i])
+ {
+ umost[i] = 1;
+ dmost[i] = 0;
+ numhits--;
+ }
+ for(i=mirrorsx2+1; i<xdimen; i++)
+ if (umost[i] <= dmost[i])
+ {
+ umost[i] = 1;
+ dmost[i] = 0;
+ numhits--;
+ }
+
+ drawalls(0L);
+ numbunches--;
+ bunchfirst[0] = bunchfirst[numbunches];
+ bunchlast[0] = bunchlast[numbunches];
+
+ mirrorsy1 = min(umost[mirrorsx1],umost[mirrorsx2]);
+ mirrorsy2 = max(dmost[mirrorsx1],dmost[mirrorsx2]);
+ }
+
+ // scansector has generated the bunches, it is now time to see which ones to render.
+ // numhits is the number of column of pixels to draw: (if the screen is 320x200 then numhits starts at 200).
+ // Due to rounding error, not all columns may be drawn so an additional stop condition is here:
+ // When every bunches have been tested for rendition.
+ while ((numbunches > 0) && (numhits > 0))
+ {
+ // tempbuf is used to mark which bunches have been elected as "closest".
+ // if tempbug[x] == 1 then it should be skipped.
+ clearbuf(&tempbuf[0],(int32_t)((numbunches+3)>>2),0L);
+
+ /* Almost works, but not quite :( */
+ closest = 0;
+ tempbuf[closest] = 1;
+ for(i=1; i<numbunches; i++)
+ {
+ if ((j = bunchfront(i,closest)) < 0)
+ continue;
+ tempbuf[i] = 1;
+ if (j == 0){
+ tempbuf[closest] = 1;
+ closest = i;
+ }
+ }
+
+ /* Double-check */
+ for(i=0; i<numbunches; i++)
+ {
+ if (tempbuf[i])
+ continue;
+ if ((j = bunchfront(i,closest)) < 0)
+ continue;
+ tempbuf[i] = 1;
+ if (j == 0){
+ tempbuf[closest] = 1;
+ closest = i, i = 0;
+ }
+ }
+
+ //Draw every solid walls with ceiling/floor in the bunch "closest"
+ drawalls(closest);
+
+ if (automapping)
+ {
+ for(z=bunchfirst[closest]; z>=0; z=bunchWallsList[z])
+ show2dwall[pvWalls[z].worldWallId>>3] |=
+ pow2char [pvWalls[z].worldWallId&7];
+ }
+
+ //Since we just rendered a bunch, lower the current stack element so we can treat the next item
+ numbunches--;
+ //...and move the bunch at the top of the stack so we won't iterate on it again...
+ bunchfirst[closest] = bunchfirst[numbunches];
+ bunchlast[closest] = bunchlast[numbunches];
+ }
+}
+
+
+static int spritewallfront (spritetype *s, int32_t w)
+{
+ walltype *wal;
+ int32_t x1, y1;
+
+ wal = &wall[w];
+ x1 = wal->x;
+ y1 = wal->y;
+ wal = &wall[wal->point2];
+ return (dmulscale32(wal->x-x1,s->y-y1,-(s->x-x1),wal->y-y1) >= 0);
+}
+
+
+static void transmaskvline(int32_t x)
+{
+ int32_t vplc, vinc, i, palookupoffs;
+ intptr_t bufplc, p;
+ short y1v, y2v;
+
+ if ((x < 0) || (x >= xdimen)) return;
+
+ y1v = max(uwall[x],startumost[x+windowx1]-windowy1);
+ y2v = min(dwall[x],startdmost[x+windowx1]-windowy1);
+ y2v--;
+ if (y2v < y1v) return;
+
+ palookupoffs = (int32_t)FP_OFF(palookup[globalpal]) + (getpalookup((int32_t)mulscale16(swall[x],globvis),globalshade)<<8);
+
+ vinc = swall[x]*globalyscale;
+ vplc = globalzd + vinc*(y1v-globalhoriz+1);
+
+ i = lwall[x]+globalxpanning;
+
+ if (i >= tiles[globalpicnum].dim.width)
+ i %= tiles[globalpicnum].dim.width;
+
+ bufplc = tiles[globalpicnum].data+i*tiles[globalpicnum].dim.height;
+
+ p = ylookup[y1v]+x+frameoffset;
+
+ tvlineasm1(vinc,palookupoffs,y2v-y1v,vplc,bufplc,p);
+
+ transarea += y2v-y1v;
+}
+
+static void transmaskvline2 (int32_t x)
+{
+ int32_t y1, y2, x2;
+ intptr_t i;
+ short y1ve[2], y2ve[2];
+
+ if ((x < 0) || (x >= xdimen)) return;
+ if (x == xdimen-1) {
+ transmaskvline(x);
+ return;
+ }
+
+ x2 = x+1;
+
+ y1ve[0] = max(uwall[x],startumost[x+windowx1]-windowy1);
+ y2ve[0] = min(dwall[x],startdmost[x+windowx1]-windowy1)-1;
+ if (y2ve[0] < y1ve[0]) {
+ transmaskvline(x2);
+ return;
+ }
+ y1ve[1] = max(uwall[x2],startumost[x2+windowx1]-windowy1);
+ y2ve[1] = min(dwall[x2],startdmost[x2+windowx1]-windowy1)-1;
+ if (y2ve[1] < y1ve[1]) {
+ transmaskvline(x);
+ return;
+ }
+
+ palookupoffse[0] = (int32_t)FP_OFF(palookup[globalpal]) + (getpalookup((int32_t)mulscale16(swall[x],globvis),globalshade)<<8);
+ palookupoffse[1] = (int32_t)FP_OFF(palookup[globalpal]) + (getpalookup((int32_t)mulscale16(swall[x2],globvis),globalshade)<<8);
+
+ setuptvlineasm2(globalshiftval,palookupoffse[0],palookupoffse[1]);
+
+ vince[0] = swall[x]*globalyscale;
+ vince[1] = swall[x2]*globalyscale;
+ vplce[0] = globalzd + vince[0]*(y1ve[0]-globalhoriz+1);
+ vplce[1] = globalzd + vince[1]*(y1ve[1]-globalhoriz+1);
+
+ i = lwall[x] + globalxpanning;
+ if (i >= tiles[globalpicnum].dim.width)
+ i %= tiles[globalpicnum].dim.width;
+ bufplce[0] = tiles[globalpicnum].data+i*tiles[globalpicnum].dim.height;
+
+ i = lwall[x2] + globalxpanning;
+ if (i >= tiles[globalpicnum].dim.width)
+ i %= tiles[globalpicnum].dim.width;
+ bufplce[1] = tiles[globalpicnum].data+i*tiles[globalpicnum].dim.height;
+
+
+ y1 = max(y1ve[0],y1ve[1]);
+ y2 = min(y2ve[0],y2ve[1]);
+
+ i = x+frameoffset;
+
+ if (y1ve[0] != y1ve[1])
+ {
+ if (y1ve[0] < y1)
+ vplce[0] = tvlineasm1(vince[0],palookupoffse[0],y1-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+i);
+ else
+ vplce[1] = tvlineasm1(vince[1],palookupoffse[1],y1-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+i+1);
+ }
+
+ if (y2 > y1)
+ {
+ asm1 = vince[1];
+ asm2 = ylookup[y2]+i+1;
+ tvlineasm2(vplce[1],vince[0],bufplce[0],bufplce[1],vplce[0],ylookup[y1]+i);
+ transarea += ((y2-y1)<<1);
+ }
+ else
+ {
+ asm1 = vplce[0];
+ asm2 = vplce[1];
+ }
+
+ if (y2ve[0] > y2ve[1])
+ tvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y2-1,asm1,bufplce[0],ylookup[y2+1]+i);
+ else if (y2ve[0] < y2ve[1])
+ tvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y2-1,asm2,bufplce[1],ylookup[y2+1]+i+1);
+
+ faketimerhandler();
+}
+
+static void transmaskwallscan(int32_t x1, int32_t x2)
+{
+ int32_t x;
+
+ setgotpic(globalpicnum);
+
+ //Tile dimensions are invalid
+ if ((tiles[globalpicnum].dim.width <= 0) ||
+ (tiles[globalpicnum].dim.height <= 0))
+ return;
+
+ TILE_MakeAvailable(globalpicnum);
+
+ x = x1;
+ while ((startumost[x+windowx1] > startdmost[x+windowx1]) && (x <= x2)) x++;
+ if ((x <= x2) && (x&1)) transmaskvline(x), x++;
+ while (x < x2) transmaskvline2(x), x += 2;
+ while (x <= x2) transmaskvline(x), x++;
+ faketimerhandler();
+}
+
+int loadboard(char *filename, int32_t *daposx, int32_t *daposy,
+ int32_t *daposz, short *daang, short *dacursectnum)
+{
+ int x;
+ short fil, i, numsprites;
+ sectortype *sect;
+ spritetype *s;
+ walltype *w;
+
+ x = 0;
+
+ // FIX_00058: Save/load game crash in both single and multiplayer
+ // We have to reset those arrays since the same
+ // arrays are used as temporary space in the
+ // compilecons() function like "label = (uint8_t *)&sprite[0];"
+ // to save memory space I guess.
+ // Not reseting the array will leave dumps fooling
+ // the function saveplayer(), eg at if(actorscrptr[PN] == 0)
+ // where PN is sprite[i].picnum was beyong actorscrptr[] size)
+ memset(sprite, 0, sizeof(sprite));
+ memset(sector, 0, sizeof(sector));
+ memset(wall, 0, sizeof(wall));
+
+ if ((fil = kopen4load(filename, 0)) == -1)
+ {
+ mapversion = 7L;
+ return(-1);
+ }
+
+ kread32(fil,&mapversion);
+ if (mapversion != 7L) return(-1);
+
+ initspritelists();
+
+ clearbuf(&show2dsector[0],(int32_t)((MAXSECTORS+3)>>5),0L);
+ clearbuf(&show2dsprite[0],(int32_t)((MAXSPRITES+3)>>5),0L);
+ clearbuf(&show2dwall[0],(int32_t)((MAXWALLS+3)>>5),0L);
+
+ kread32(fil,daposx);
+ kread32(fil,daposy);
+ kread32(fil,daposz);
+ kread16(fil,daang);
+ kread16(fil,dacursectnum);
+ kread16(fil,&numsectors);
+
+ for (x = 0, sect = &sector[0]; x < numsectors; x++, sect++)
+ {
+ kread16(fil,&sect->wallptr);
+ kread16(fil,&sect->wallnum);
+ kread32(fil,&sect->ceilingz);
+ kread32(fil,&sect->floorz);
+ kread16(fil,&sect->ceilingstat);
+ kread16(fil,&sect->floorstat);
+ kread16(fil,&sect->ceilingpicnum);
+ kread16(fil,&sect->ceilingheinum);
+ kread8(fil,(uint8_t *)&sect->ceilingshade);
+ kread8(fil,(uint8_t *)&sect->ceilingpal);
+ kread8(fil,(uint8_t *)&sect->ceilingxpanning);
+ kread8(fil,(uint8_t *)&sect->ceilingypanning);
+ kread16(fil,&sect->floorpicnum);
+ kread16(fil,&sect->floorheinum);
+ kread8(fil,(uint8_t *)&sect->floorshade);
+ kread8(fil,(uint8_t *)&sect->floorpal);
+ kread8(fil,(uint8_t *)&sect->floorxpanning);
+ kread8(fil,(uint8_t *)&sect->floorypanning);
+ kread8(fil,(uint8_t *)&sect->visibility);
+ kread8(fil,(uint8_t *)&sect->filler);
+ kread16(fil,&sect->lotag);
+ kread16(fil,&sect->hitag);
+ kread16(fil,&sect->extra);
+ }
+
+ kread16(fil,&numwalls);
+ for (x = 0, w = &wall[0]; x < numwalls; x++, w++)
+ {
+ kread32(fil,&w->x);
+ kread32(fil,&w->y);
+ kread16(fil,&w->point2);
+ kread16(fil,&w->nextwall);
+ kread16(fil,&w->nextsector);
+ kread16(fil,&w->cstat);
+ kread16(fil,&w->picnum);
+ kread16(fil,&w->overpicnum);
+ kread8(fil,(uint8_t *)&w->shade);
+ kread8(fil,&w->pal);
+ kread8(fil,&w->xrepeat);
+ kread8(fil,&w->yrepeat);
+ kread8(fil,&w->xpanning);
+ kread8(fil,&w->ypanning);
+ kread16(fil,&w->lotag);
+ kread16(fil,&w->hitag);
+ kread16(fil,&w->extra);
+ }
+
+ kread16(fil,&numsprites);
+ for (x = 0, s = &sprite[0]; x < numsprites; x++, s++)
+ {
+ kread32(fil,&s->x);
+ kread32(fil,&s->y);
+ kread32(fil,&s->z);
+ kread16(fil,&s->cstat);
+ kread16(fil,&s->picnum);
+ kread8(fil,(uint8_t *)&s->shade);
+ kread8(fil,(uint8_t *)&s->pal);
+ kread8(fil,(uint8_t *)&s->clipdist);
+ kread8(fil,(uint8_t *)&s->filler);
+ kread8(fil,(uint8_t *)&s->xrepeat);
+ kread8(fil,(uint8_t *)&s->yrepeat);
+ kread8(fil,(uint8_t *)&s->xoffset);
+ kread8(fil,(uint8_t *)&s->yoffset);
+ kread16(fil,&s->sectnum);
+ kread16(fil,&s->statnum);
+ kread16(fil,&s->ang);
+ kread16(fil,&s->owner);
+ kread16(fil,&s->xvel);
+ kread16(fil,&s->yvel);
+ kread16(fil,&s->zvel);
+ kread16(fil,&s->lotag);
+ kread16(fil,&s->hitag);
+ kread16(fil,&s->extra);
+ }
+
+
+ for(i=0; i<numsprites; i++)
+ insertsprite(sprite[i].sectnum,sprite[i].statnum);
+
+ /* Must be after loading sectors, etc! */
+ updatesector(*daposx,*daposy,dacursectnum);
+
+ kclose(fil);
+
+ // FIX_00009: Show map CRC and GRP file version of each player in case of Out Of Synch
+
+ mapCRC = crc16((uint8_t *)sector, numsectors*sizeof(sectortype));
+ mapCRC += crc16((uint8_t *)wall, numwalls*sizeof(walltype));
+ mapCRC += crc16((uint8_t *)sprite, numsprites*sizeof(spritetype));
+
+ return(0);
+}
+
+
+static void write32(int f, int32_t val)
+{
+ val = BUILDSWAP_INTEL32(val);
+ write(f, &val, 4);
+}
+
+static void write16(int f, short val)
+{
+ val = BUILDSWAP_INTEL16(val);
+ write(f, &val, 2);
+}
+
+static void write8(int f, uint8_t val)
+{
+ write(f, &val, 1);
+}
+
+
+int saveboard(char *filename, int32_t *daposx, int32_t *daposy,
+ int32_t *daposz, short *daang, short *dacursectnum)
+{
+ int fil;
+ int x;
+ short i, j, numsprites;
+ int permissions = 0;
+ walltype *w;
+ sectortype *sect;
+
+#if ((defined PLATFORM_DOS) || (defined PLATFORM_WIN32))
+ permissions = S_IWRITE;
+#elif (defined PLATFORM_UNIX)
+ permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+#elif (defined PLATFORM_ROCKBOX)
+ permissions = 0644;
+#endif
+
+ if ((fil = rb->open(filename,
+ O_BINARY|O_TRUNC|O_CREAT|O_WRONLY,
+ permissions)) == -1)
+ {
+ return(-1);
+ }
+
+ write32(fil,mapversion);
+
+ write32(fil,*daposx);
+ write32(fil,*daposy);
+ write32(fil,*daposz);
+ write16(fil,*daang);
+ write16(fil,*dacursectnum);
+
+ write16(fil,numsectors);
+ for (x = 0, sect = &sector[0]; x < numsectors; x++, sect++)
+ {
+ write16(fil,sect->wallptr);
+ write16(fil,sect->wallnum);
+ write32(fil,sect->ceilingz);
+ write32(fil,sect->floorz);
+ write16(fil,sect->ceilingstat);
+ write16(fil,sect->floorstat);
+ write16(fil,sect->ceilingpicnum);
+ write16(fil,sect->ceilingheinum);
+ write8(fil,sect->ceilingshade);
+ write8(fil,sect->ceilingpal);
+ write8(fil,sect->ceilingxpanning);
+ write8(fil,sect->ceilingypanning);
+ write16(fil,sect->floorpicnum);
+ write16(fil,sect->floorheinum);
+ write8(fil,sect->floorshade);
+ write8(fil,sect->floorpal);
+ write8(fil,sect->floorxpanning);
+ write8(fil,sect->floorypanning);
+ write8(fil,sect->visibility);
+ write8(fil,sect->filler);
+ write16(fil,sect->lotag);
+ write16(fil,sect->hitag);
+ write16(fil,sect->extra);
+ }
+
+ write16(fil,numwalls);
+ for (x = 0, w = &wall[0]; x < numwalls; x++, w++)
+ {
+ write32(fil,w->x);
+ write32(fil,w->y);
+ write16(fil,w->point2);
+ write16(fil,w->nextwall);
+ write16(fil,w->nextsector);
+ write16(fil,w->cstat);
+ write16(fil,w->picnum);
+ write16(fil,w->overpicnum);
+ write8(fil,w->shade);
+ write8(fil,w->pal);
+ write8(fil,w->xrepeat);
+ write8(fil,w->yrepeat);
+ write8(fil,w->xpanning);
+ write8(fil,w->ypanning);
+ write16(fil,w->lotag);
+ write16(fil,w->hitag);
+ write16(fil,w->extra);
+ }
+
+ numsprites = 0;
+ for(j=0; j<MAXSTATUS; j++)
+ {
+ i = headspritestat[j];
+ while (i != -1)
+ {
+ numsprites++;
+ i = nextspritestat[i];
+ }
+ }
+ write16(fil,numsprites);
+
+ for(j=0; j<MAXSTATUS; j++)
+ {
+ i = headspritestat[j];
+ while (i != -1)
+ {
+ spritetype *s = &sprite[i];
+ write32(fil,s->x);
+ write32(fil,s->y);
+ write32(fil,s->z);
+ write16(fil,s->cstat);
+ write16(fil,s->picnum);
+ write8(fil,s->shade);
+ write8(fil,s->pal);
+ write8(fil,s->clipdist);
+ write8(fil,s->filler);
+ write8(fil,s->xrepeat);
+ write8(fil,s->yrepeat);
+ write8(fil,s->xoffset);
+ write8(fil,s->yoffset);
+ write16(fil,s->sectnum);
+ write16(fil,s->statnum);
+ write16(fil,s->ang);
+ write16(fil,s->owner);
+ write16(fil,s->xvel);
+ write16(fil,s->yvel);
+ write16(fil,s->zvel);
+ write16(fil,s->lotag);
+ write16(fil,s->hitag);
+ write16(fil,s->extra);
+
+ i = nextspritestat[i];
+ }
+ }
+
+ close(fil);
+ return(0);
+}
+
+
+static void initksqrt(void)
+{
+ int32_t i, j, k;
+
+ j = 1;
+ k = 0;
+ for(i=0; i<4096; i++)
+ {
+ if (i >= j) {
+ j <<= 2;
+ k++;
+ }
+ sqrtable[i] = (uint16_t)(msqrtasm((i<<18)+131072)<<1);
+ shlookup[i] = (k<<1)+((10-k)<<8);
+ if (i < 256) shlookup[i+4096] = ((k+6)<<1)+((10-(k+6))<<8);
+ }
+}
+
+
+static void loadtables(void)
+{
+ int32_t i, fil;
+
+ if (tablesloaded == 0)
+ {
+ initksqrt();
+
+ for(i=0; i<2048; i++) reciptable[i] = divscale30(2048L,i+2048);
+
+ if ((fil = TCkopen4load("tables.dat",0)) != -1)
+ {
+ for (i = 0; i < 2048; i++)
+ kread16(fil,&sintable[i]);
+
+ for (i = 0; i < 640; i++)
+ kread16(fil,&radarang[i]);
+
+ for(i=0; i<640; i++) radarang[1279-i] = -radarang[i];
+ kread(fil,textfont,1024);
+ kread(fil,smalltextfont,1024);
+ kread(fil,britable,1024);
+ kclose(fil);
+ }
+ tablesloaded = 1;
+ }
+}
+
+
+static void initfastcolorlookup(int32_t rscale, int32_t gscale, int32_t bscale)
+{
+ int32_t i, j, x, y, z;
+ uint8_t *pal1;
+
+ j = 0;
+ for(i=64; i>=0; i--)
+ {
+ /*j = (i-64)*(i-64);*/
+ rdist[i] = rdist[128-i] = j*rscale;
+ gdist[i] = gdist[128-i] = j*gscale;
+ bdist[i] = bdist[128-i] = j*bscale;
+ j += 129-(i<<1);
+ }
+
+ clearbufbyte((void *)FP_OFF(colhere),sizeof(colhere),0L);
+ clearbufbyte((void *)FP_OFF(colhead),sizeof(colhead),0L);
+
+ pal1 = &palette[768-3];
+ for(i=255; i>=0; i--,pal1-=3)
+ {
+ j = (pal1[0]>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ+(pal1[1]>>3)*FASTPALGRIDSIZ+(pal1[2]>>3)+FASTPALGRIDSIZ*FASTPALGRIDSIZ+FASTPALGRIDSIZ+1;
+ if (colhere[j>>3]&pow2char[j&7]) colnext[i] = colhead[j];
+ else colnext[i] = -1;
+ colhead[j] = i;
+ colhere[j>>3] |= pow2char[j&7];
+ }
+
+ i = 0;
+ for(x=-FASTPALGRIDSIZ*FASTPALGRIDSIZ; x<=FASTPALGRIDSIZ*FASTPALGRIDSIZ; x+=FASTPALGRIDSIZ*FASTPALGRIDSIZ)
+ for(y=-FASTPALGRIDSIZ; y<=FASTPALGRIDSIZ; y+=FASTPALGRIDSIZ)
+ for(z=-1; z<=1; z++)
+ colscan[i++] = x+y+z;
+ i = colscan[13];
+ colscan[13] = colscan[26];
+ colscan[26] = i;
+}
+
+extern uint8_t lastPalette[768];
+static void loadpalette(void)
+{
+ int32_t k, fil;
+
+
+ if (paletteloaded != 0)
+ return;
+
+ if ((fil = TCkopen4load("palette.dat",0)) < 0)
+ return;
+
+ kread(fil,palette,768);
+
+ //CODE EXPLORATION
+ //WritePaletteToFile(palette,"palette.tga",16, 16);
+ memcpy(lastPalette, palette, 768);
+
+
+ kread16(fil,&numpalookups);
+
+ //CODE EXPLORATION
+ //printf("Num palettes lookup: %d.\n",numpalookups);
+
+ if ((palookup[0] = (uint8_t *)kkmalloc(numpalookups<<8)) == NULL)
+ allocache(&palookup[0],numpalookups<<8,&permanentlock);
+
+ //Transluctent pallete is 65KB.
+ if ((transluc = (uint8_t *)kkmalloc(65536)) == NULL)
+ allocache(&transluc,65536,&permanentlock);
+
+ globalpalwritten = palookup[0];
+ globalpal = 0;
+
+
+
+
+ kread(fil,palookup[globalpal],numpalookups<<8);
+
+
+ /*kread(fil,transluc,65536);*/
+ for (k = 0; k < (65536 / 4); k++)
+ kread32(fil, ((int32_t *) transluc) + k);
+
+
+
+ kclose(fil);
+
+ initfastcolorlookup(30L,59L,11L);
+
+ paletteloaded = 1;
+
+}
+
+
+
+int setgamemode(uint8_t davidoption, int32_t daxdim, int32_t daydim)
+{
+ strcpy(kensmessage,"!!!! BUILD engine&tools programmed by Ken Silverman of E.G. RI. (c) Copyright 1995 Ken Silverman. Summary: BUILD = Ken. !!!!");
+
+ return(_setgamemode(davidoption, daxdim, daydim));
+}
+
+
+void initengine(void)
+{
+ int32_t i;
+
+ loadtables();
+
+ xyaspect = -1;
+
+ pskyoff[0] = 0;
+ pskybits = 0;
+
+ parallaxtype = 2;
+ parallaxyoffs = 0L;
+ parallaxyscale = 65536;
+ showinvisibility = 0;
+
+ paletteloaded = 0;
+
+ searchit = 0;
+ searchstat = -1;
+
+ for(i=0; i<MAXPALOOKUPS; i++)
+ palookup[i] = NULL;
+
+ for(i=0 ; i < MAXTILES ; i++)
+ tiles[i].data = NULL;
+
+ clearbuf(&show2dsector[0],(int32_t)((MAXSECTORS+3)>>5),0L);
+ clearbuf(&show2dsprite[0],(int32_t)((MAXSPRITES+3)>>5),0L);
+ clearbuf(&show2dwall[0],(int32_t)((MAXWALLS+3)>>5),0L);
+ automapping = 0;
+
+ validmodecnt = 0;
+
+ pointhighlight = -1;
+ linehighlight = -1;
+ highlightcnt = 0;
+
+ totalclock = 0;
+ visibility = 512;
+ parallaxvisibility = 512;
+
+ loadpalette();
+}
+
+
+void uninitengine(void)
+{
+ if (transluc != NULL) {
+ kkfree(transluc);
+ transluc = NULL;
+ }
+ if (pic != NULL) {
+ kkfree(pic);
+ pic = NULL;
+ }
+ if (artfil != -1) kclose(artfil);
+ _uninitengine(); /* video driver specific. */
+}
+
+
+/* Assume npoints=4 with polygon on &rx1,&ry1 */
+//FCS This is horrible to read: I hate you.
+static int clippoly4(int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2)
+{
+ int32_t n, nn, z, zz, x, x1, x2, y, y1, y2, t;
+
+ nn = 0;
+ z = 0;
+ do
+ {
+ zz = ((z+1)&3);
+
+
+ x1 = pvWalls[z] .cameraSpaceCoo[0][VEC_X];
+ x2 = pvWalls[zz].cameraSpaceCoo[0][VEC_X]-x1;
+
+ if ((cx1 <= x1) && (x1 <= cx2)){
+ pvWalls[nn] .cameraSpaceCoo[1][VEC_X] = x1;
+ pvWalls[nn] .cameraSpaceCoo[1][VEC_Y] = pvWalls[z] .cameraSpaceCoo[0][VEC_Y];
+ nn++;
+ }
+
+ if (x2 <= 0)
+ x = cx2;
+ else
+ x = cx1;
+
+ t = x-x1;
+
+ if (((t-x2)^t) < 0){
+ pvWalls[nn] .cameraSpaceCoo[1][VEC_X] = x;
+ pvWalls[nn] .cameraSpaceCoo[1][VEC_Y] = pvWalls[z].cameraSpaceCoo[0][VEC_Y] +
+ scale(t,pvWalls[zz].cameraSpaceCoo[0][VEC_Y]-pvWalls[z].cameraSpaceCoo[0][VEC_Y],x2);
+ nn++;
+ }
+
+ if (x2 <= 0)
+ x = cx1;
+ else
+ x = cx2;
+
+ t = x-x1;
+
+ if (((t-x2)^t) < 0){
+ pvWalls[nn] .cameraSpaceCoo[1][VEC_X] = x;
+ pvWalls[nn] .cameraSpaceCoo[1][VEC_Y] = pvWalls[z] .cameraSpaceCoo[0][VEC_Y]+
+ scale(t,pvWalls[zz].cameraSpaceCoo[0][VEC_Y]-pvWalls[z].cameraSpaceCoo[0][VEC_Y],x2);
+ nn++;
+ }
+ z = zz;
+ } while (z != 0);
+ if (nn < 3) return(0);
+
+ n = 0;
+ z = 0;
+ do
+ {
+ zz = z+1;
+ if (zz == nn)
+ zz = 0;
+
+ y1 = pvWalls[z] .cameraSpaceCoo[1][VEC_Y];
+ y2 = pvWalls[zz].cameraSpaceCoo[1][VEC_Y]-y1;
+
+ if ((cy1 <= y1) && (y1 <= cy2)){
+ pvWalls[n] .cameraSpaceCoo[0][VEC_Y] = y1;
+ pvWalls[n] .cameraSpaceCoo[0][VEC_X] = pvWalls[z] .cameraSpaceCoo[1][VEC_X];
+ n++;
+ }
+ if (y2 <= 0) y = cy2;
+ else y = cy1;
+ t = y-y1;
+ if (((t-y2)^t) < 0){
+ pvWalls[n] .cameraSpaceCoo[0][VEC_Y] = y;
+ pvWalls[n] .cameraSpaceCoo[0][VEC_X] =
+ pvWalls[z] .cameraSpaceCoo[1][VEC_X]+scale(t,
+ pvWalls[zz].cameraSpaceCoo[1][VEC_X]-
+ pvWalls[z] .cameraSpaceCoo[1][VEC_X],y2);
+ n++;
+ }
+
+ if (y2 <= 0) y = cy1;
+ else y = cy2;
+ t = y-y1;
+ if (((t-y2)^t) < 0){
+ pvWalls[n] .cameraSpaceCoo[0][VEC_Y] = y;
+ pvWalls[n] .cameraSpaceCoo[0][VEC_X] =
+ pvWalls[z] .cameraSpaceCoo[1][VEC_X]+scale(t,
+ pvWalls[zz].cameraSpaceCoo[1][VEC_X]-
+ pvWalls[z ].cameraSpaceCoo[1][VEC_X],y2);
+ n++;
+ }
+ z = zz;
+ } while (z != 0);
+ return(n);
+}
+
+
+
+static void dorotatesprite (int32_t sx, int32_t sy, int32_t z, short a, short picnum,
+ int8_t dashade, uint8_t dapalnum, uint8_t dastat, int32_t cx1,
+ int32_t cy1, int32_t cx2, int32_t cy2)
+{
+ int32_t cosang, sinang, v, nextv, dax1, dax2, oy, bx, by, ny1, ny2;
+ int32_t i, x, y, x1, y1, x2, y2, gx1, gy1;
+ uint8_t* bufplc;
+ uint8_t* palookupoffs;
+ uint8_t* p;
+ int32_t xoff, yoff, npoints, yplc, yinc, lx, rx, xx, xend;
+ int32_t xv, yv, xv2, yv2, obuffermode=0, qlinemode=0, y1ve[4], y2ve[4], u4, d4;
+ uint8_t bad;
+
+ short tileWidht, tileHeight;
+
+ tileWidht = tiles[picnum].dim.width;
+ tileHeight = tiles[picnum].dim.height;
+
+ if (dastat&16) {
+ xoff = 0;
+ yoff = 0;
+ }
+ else{
+ xoff = (int32_t)((int8_t )((tiles[picnum].animFlags>>8)&255))+(tileWidht>>1);
+ yoff = (int32_t)((int8_t )((tiles[picnum].animFlags>>16)&255))+(tileHeight>>1);
+ }
+
+ if (dastat&4)
+ yoff = tileHeight-yoff;
+
+ cosang = sintable[(a+512)&2047];
+ sinang = sintable[a&2047];
+
+ if ((dastat&2) != 0) /* Auto window size scaling */
+ {
+ if ((dastat&8) == 0)
+ {
+ x = xdimenscale; /* = scale(xdimen,yxaspect,320); */
+ if (stereomode) x = scale(windowx2-windowx1+1,yxaspect,320);
+ sx = ((cx1+cx2+2)<<15)+scale(sx-(320<<15),xdimen,320);
+ sy = ((cy1+cy2+2)<<15)+mulscale16(sy-(200<<15),x);
+ }
+ else
+ {
+ /*
+ * If not clipping to startmosts, & auto-scaling on, as a
+ * hard-coded bonus, scale to full screen instead
+ */
+ x = scale(xdim,yxaspect,320);
+ sx = (xdim<<15)+32768+scale(sx-(320<<15),xdim,320);
+ sy = (ydim<<15)+32768+mulscale16(sy-(200<<15),x);
+ }
+ z = mulscale16(z,x);
+ }
+
+ xv = mulscale14(cosang,z);
+ yv = mulscale14(sinang,z);
+ if (((dastat&2) != 0) || ((dastat&8) == 0)) /* Don't aspect unscaled perms */
+ {
+ xv2 = mulscale16(xv,xyaspect);
+ yv2 = mulscale16(yv,xyaspect);
+ }
+ else
+ {
+ xv2 = xv;
+ yv2 = yv;
+ }
+
+
+ //Taking care of the Y coordinates.
+ pvWalls[0].cameraSpaceCoo[0][VEC_Y] = sy - (yv*xoff + xv*yoff);
+ pvWalls[1].cameraSpaceCoo[0][VEC_Y] = pvWalls[0].cameraSpaceCoo[0][VEC_Y] + yv * tileWidht;
+ pvWalls[3].cameraSpaceCoo[0][VEC_Y] = pvWalls[0].cameraSpaceCoo[0][VEC_Y] + xv * tileHeight;
+
+ pvWalls[2].cameraSpaceCoo[0][VEC_Y] = pvWalls[1].cameraSpaceCoo[0][VEC_Y] +
+ pvWalls[3].cameraSpaceCoo[0][VEC_Y] -
+ pvWalls[0].cameraSpaceCoo[0][VEC_Y] ;
+
+ i = (cy1<<16);
+
+ if ((pvWalls[0].cameraSpaceCoo[0][VEC_Y]<i) &&
+ (pvWalls[1].cameraSpaceCoo[0][VEC_Y]<i) &&
+ (pvWalls[2].cameraSpaceCoo[0][VEC_Y]<i) &&
+ (pvWalls[3].cameraSpaceCoo[0][VEC_Y]<i))
+ return;
+
+ i = (cy2<<16);
+
+ if ((pvWalls[0].cameraSpaceCoo[0][VEC_Y]>i) &&
+ (pvWalls[1].cameraSpaceCoo[0][VEC_Y]>i) &&
+ (pvWalls[2].cameraSpaceCoo[0][VEC_Y]>i) &&
+ (pvWalls[3].cameraSpaceCoo[0][VEC_Y]>i))
+ return;
+
+
+
+ //Taking care of the X coordinates.
+ pvWalls[0].cameraSpaceCoo[0][VEC_X] = sx - (xv2*xoff - yv2*yoff);
+ pvWalls[1].cameraSpaceCoo[0][VEC_X] = pvWalls[0].cameraSpaceCoo[0][VEC_X] + xv2 * tileWidht;
+ pvWalls[3].cameraSpaceCoo[0][VEC_X] = pvWalls[0].cameraSpaceCoo[0][VEC_X] - yv2 * tileHeight;
+ pvWalls[2].cameraSpaceCoo[0][VEC_X] = pvWalls[1].cameraSpaceCoo[0][VEC_X] +
+ pvWalls[3].cameraSpaceCoo[0][VEC_X] -
+ pvWalls[0].cameraSpaceCoo[0][VEC_X] ;
+
+ i = (cx1<<16);
+ if ((pvWalls[0].cameraSpaceCoo[0][VEC_X]<i) &&
+ (pvWalls[1].cameraSpaceCoo[0][VEC_X]<i) &&
+ (pvWalls[2].cameraSpaceCoo[0][VEC_X]<i) &&
+ (pvWalls[3].cameraSpaceCoo[0][VEC_X]<i))
+ return;
+
+ i = (cx2<<16);
+ if ((pvWalls[0].cameraSpaceCoo[0][VEC_X]>i) &&
+ (pvWalls[1].cameraSpaceCoo[0][VEC_X]>i) &&
+ (pvWalls[2].cameraSpaceCoo[0][VEC_X]>i) &&
+ (pvWalls[3].cameraSpaceCoo[0][VEC_X]>i))
+ return;
+
+
+
+
+
+
+
+
+ gx1 = pvWalls[0].cameraSpaceCoo[0][VEC_X];
+ gy1 = pvWalls[0].cameraSpaceCoo[0][VEC_Y]; /* back up these before clipping */
+
+ if ((npoints = clippoly4(cx1<<16,cy1<<16,(cx2+1)<<16,(cy2+1)<<16)) < 3) return;
+
+ lx = pvWalls[0].cameraSpaceCoo[0][VEC_X];
+ rx = pvWalls[0].cameraSpaceCoo[0][VEC_X];
+
+ nextv = 0;
+ for(v=npoints-1; v>=0; v--)
+ {
+ x1 = pvWalls[ v].cameraSpaceCoo[0][VEC_X];
+ x2 = pvWalls[nextv].cameraSpaceCoo[0][VEC_X];
+ dax1 = (x1>>16);
+ if (x1 < lx) lx = x1;
+ dax2 = (x2>>16);
+ if (x1 > rx) rx = x1;
+ if (dax1 != dax2)
+ {
+ y1 = pvWalls[ v].cameraSpaceCoo[0][VEC_Y];
+ y2 = pvWalls[nextv].cameraSpaceCoo[0][VEC_Y];
+ yinc = divscale16(y2-y1,x2-x1);
+ if (dax2 > dax1)
+ {
+ yplc = y1 + mulscale16((dax1<<16)+65535-x1,yinc);
+ qinterpolatedown16short((int32_t *)(&uplc[dax1]),dax2-dax1,yplc,yinc);
+ }
+ else
+ {
+ yplc = y2 + mulscale16((dax2<<16)+65535-x2,yinc);
+ qinterpolatedown16short((int32_t *)(&dplc[dax2]),dax1-dax2,yplc,yinc);
+ }
+ }
+ nextv = v;
+ }
+
+ TILE_MakeAvailable(picnum);
+
+ setgotpic(picnum);
+ bufplc = tiles[picnum].data;
+
+ palookupoffs = palookup[dapalnum] + (getpalookup(0L,(int32_t)dashade)<<8);
+
+ i = divscale32(1L,z);
+ xv = mulscale14(sinang,i);
+ yv = mulscale14(cosang,i);
+ if (((dastat&2) != 0) || ((dastat&8) == 0)) /* Don't aspect unscaled perms */
+ {
+ yv2 = mulscale16(-xv,yxaspect);
+ xv2 = mulscale16(yv,yxaspect);
+ }
+ else
+ {
+ yv2 = -xv;
+ xv2 = yv;
+ }
+
+ x1 = (lx>>16);
+ x2 = (rx>>16);
+
+ oy = 0;
+ x = (x1<<16)-1-gx1;
+ y = (oy<<16)+65535-gy1;
+ bx = dmulscale16(x,xv2,y,xv);
+ by = dmulscale16(x,yv2,y,yv);
+ if (dastat&4) {
+ yv = -yv;
+ yv2 = -yv2;
+ by = (tileHeight<<16)-1-by;
+ }
+
+ if ((vidoption == 1) && (origbuffermode == 0))
+ {
+ if (dastat&128)
+ {
+ obuffermode = buffermode;
+ buffermode = 0;
+
+ }
+ }
+ else if (dastat&8)
+ permanentupdate = 1;
+
+ if ((dastat&1) == 0)
+ {
+ if (((a&1023) == 0) && (tileHeight <= 256)) /* vlineasm4 has 256 high limit! */
+ {
+ if (dastat&64)
+ setupvlineasm(24L);
+ else
+ setupmvlineasm(24L);
+
+ by <<= 8;
+ yv <<= 8;
+ yv2 <<= 8;
+
+ palookupoffse[0] = palookupoffse[1] = palookupoffse[2] = palookupoffse[3] = palookupoffs;
+ vince[0] = vince[1] = vince[2] = vince[3] = yv;
+
+ for(x=x1; x<x2; x+=4)
+ {
+ bad = 15;
+ xend = min(x2-x,4);
+ for(xx=0; xx<xend; xx++)
+ {
+ bx += xv2;
+
+ y1 = uplc[x+xx];
+ y2 = dplc[x+xx];
+ if ((dastat&8) == 0)
+ {
+ if (startumost[x+xx] > y1) y1 = startumost[x+xx];
+ if (startdmost[x+xx] < y2) y2 = startdmost[x+xx];
+ }
+ if (y2 <= y1) continue;
+
+ by += yv*(y1-oy);
+ oy = y1;
+
+ bufplce[xx] = (bx>>16)*tileHeight+bufplc;
+ vplce[xx] = by;
+ y1ve[xx] = y1;
+ y2ve[xx] = y2-1;
+ bad &= ~pow2char[xx];
+ }
+
+ p = x+frameplace;
+
+ u4 = max(max(y1ve[0],y1ve[1]),max(y1ve[2],y1ve[3]));
+ d4 = min(min(y2ve[0],y2ve[1]),min(y2ve[2],y2ve[3]));
+
+ if (dastat&64)
+ {
+ if ((bad != 0) || (u4 >= d4))
+ {
+ if (!(bad&1))
+ prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
+ if (!(bad&2))
+ prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
+ if (!(bad&4))
+ prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
+ if (!(bad&8))
+ prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
+ continue;
+ }
+
+ if (u4 > y1ve[0])
+ vplce[0] = prevlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
+ if (u4 > y1ve[1])
+ vplce[1] = prevlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
+ if (u4 > y1ve[2])
+ vplce[2] = prevlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
+ if (u4 > y1ve[3])
+ vplce[3] = prevlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
+
+ if (d4 >= u4) vlineasm4(d4-u4+1,ylookup[u4]+p);
+
+ i = p+ylookup[d4+1];
+ if (y2ve[0] > d4)
+ prevlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
+ if (y2ve[1] > d4)
+ prevlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
+ if (y2ve[2] > d4)
+ prevlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
+ if (y2ve[3] > d4)
+ prevlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
+ }
+ else
+ {
+ if ((bad != 0) || (u4 >= d4))
+ {
+ if (!(bad&1)) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-y1ve[0],vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
+ if (!(bad&2)) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-y1ve[1],vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
+ if (!(bad&4)) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-y1ve[2],vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
+ if (!(bad&8)) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-y1ve[3],vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
+ continue;
+ }
+
+ if (u4 > y1ve[0]) vplce[0] = mvlineasm1(vince[0],palookupoffse[0],u4-y1ve[0]-1,vplce[0],bufplce[0],ylookup[y1ve[0]]+p+0);
+ if (u4 > y1ve[1]) vplce[1] = mvlineasm1(vince[1],palookupoffse[1],u4-y1ve[1]-1,vplce[1],bufplce[1],ylookup[y1ve[1]]+p+1);
+ if (u4 > y1ve[2]) vplce[2] = mvlineasm1(vince[2],palookupoffse[2],u4-y1ve[2]-1,vplce[2],bufplce[2],ylookup[y1ve[2]]+p+2);
+ if (u4 > y1ve[3]) vplce[3] = mvlineasm1(vince[3],palookupoffse[3],u4-y1ve[3]-1,vplce[3],bufplce[3],ylookup[y1ve[3]]+p+3);
+
+ if (d4 >= u4) mvlineasm4(d4-u4+1,ylookup[u4]+p);
+
+ i = p+ylookup[d4+1];
+ if (y2ve[0] > d4) mvlineasm1(vince[0],palookupoffse[0],y2ve[0]-d4-1,vplce[0],bufplce[0],i+0);
+ if (y2ve[1] > d4) mvlineasm1(vince[1],palookupoffse[1],y2ve[1]-d4-1,vplce[1],bufplce[1],i+1);
+ if (y2ve[2] > d4) mvlineasm1(vince[2],palookupoffse[2],y2ve[2]-d4-1,vplce[2],bufplce[2],i+2);
+ if (y2ve[3] > d4) mvlineasm1(vince[3],palookupoffse[3],y2ve[3]-d4-1,vplce[3],bufplce[3],i+3);
+ }
+
+ faketimerhandler();
+ }
+ }
+ else
+ {
+ if (dastat&64)
+ {
+ if ((xv2&0x0000ffff) == 0)
+ {
+ qlinemode = 1;
+ setuprhlineasm4(0L,yv2<<16,(xv2>>16)*tileHeight+(yv2>>16),palookupoffs,0L,0L);
+ }
+ else
+ {
+ qlinemode = 0;
+ setuprhlineasm4(xv2<<16,yv2<<16,(xv2>>16)*tileHeight+(yv2>>16),palookupoffs,tileHeight,0L);
+ }
+ }
+ else
+ setuprmhlineasm4(xv2<<16,yv2<<16,(xv2>>16)*tileHeight+(yv2>>16),palookupoffs,tileHeight,0L);
+
+ y1 = uplc[x1];
+ if (((dastat&8) == 0) && (startumost[x1] > y1)) y1 = startumost[x1];
+ y2 = y1;
+ for(x=x1; x<x2; x++)
+ {
+ ny1 = uplc[x]-1;
+ ny2 = dplc[x];
+ if ((dastat&8) == 0)
+ {
+ if (startumost[x]-1 > ny1) ny1 = startumost[x]-1;
+ if (startdmost[x] < ny2) ny2 = startdmost[x];
+ }
+
+ if (ny1 < ny2-1)
+ {
+ if (ny1 >= y2)
+ {
+ while (y1 < y2-1)
+ {
+ y1++;
+ if ((y1&31) == 0) faketimerhandler();
+
+ /* x,y1 */
+ bx += xv*(y1-oy);
+ by += yv*(y1-oy);
+ oy = y1;
+ if (dastat&64) {
+ if (qlinemode)
+ rhlineasm4(x-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,0L ,by<<16,ylookup[y1]+x+frameplace);
+ else
+ rhlineasm4(x-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
+ } else
+ rmhlineasm4(x-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
+ }
+ y1 = ny1;
+ }
+ else
+ {
+ while (y1 < ny1)
+ {
+ y1++;
+ if ((y1&31) == 0) faketimerhandler();
+
+ /* x,y1 */
+ bx += xv*(y1-oy);
+ by += yv*(y1-oy);
+ oy = y1;
+ if (dastat&64) {
+ if (qlinemode)
+ rhlineasm4(x-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,0L,by<<16,ylookup[y1]+x+frameplace);
+ else
+ rhlineasm4(x-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
+ } else
+ rmhlineasm4(x-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
+ }
+ while (y1 > ny1) lastx[y1--] = x;
+ }
+ while (y2 > ny2)
+ {
+ y2--;
+ if ((y2&31) == 0) faketimerhandler();
+
+ /* x,y2 */
+ bx += xv*(y2-oy);
+ by += yv*(y2-oy);
+ oy = y2;
+ if (dastat&64) {
+ if (qlinemode)
+ rhlineasm4(x-lastx[y2],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,0L ,by<<16,ylookup[y2]+x+frameplace);
+ else
+ rhlineasm4(x-lastx[y2],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y2]+x+frameplace);
+ } else
+ rmhlineasm4(x-lastx[y2],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y2]+x+frameplace);
+ }
+ while (y2 < ny2) lastx[y2++] = x;
+ }
+ else
+ {
+ while (y1 < y2-1)
+ {
+ y1++;
+ if ((y1&31) == 0) faketimerhandler();
+
+ /* x,y1 */
+ bx += xv*(y1-oy);
+ by += yv*(y1-oy);
+ oy = y1;
+ if (dastat&64)
+ {
+ if (qlinemode)
+ rhlineasm4(x-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,0L ,by<<16,ylookup[y1]+x+frameplace);
+ else
+ rhlineasm4(x-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
+ }
+ else
+ rmhlineasm4(x-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x+frameplace);
+ }
+ if (x == x2-1)
+ {
+ bx += xv2;
+ by += yv2;
+ break;
+ }
+
+ y1 = uplc[x+1];
+
+ if (((dastat&8) == 0) && (startumost[x+1] > y1))
+ y1 = startumost[x+1];
+
+ y2 = y1;
+ }
+ bx += xv2;
+ by += yv2;
+ }
+ while (y1 < y2-1)
+ {
+ y1++;
+ if ((y1&31) == 0) faketimerhandler();
+
+ /* x2,y1 */
+ bx += xv*(y1-oy);
+ by += yv*(y1-oy);
+ oy = y1;
+ if (dastat&64) {
+ if (qlinemode)
+ rhlineasm4(x2-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,0L ,by<<16,ylookup[y1]+x2+frameplace);
+ else
+ rhlineasm4(x2-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x2+frameplace);
+ } else
+ rmhlineasm4(x2-lastx[y1],(bx>>16)*tileHeight+(by>>16)+bufplc,0L,bx<<16,by<<16,ylookup[y1]+x2+frameplace);
+ }
+ }
+ }
+ else
+ {
+ if ((dastat&1) == 0)
+ {
+ if (dastat&64)
+ setupspritevline(palookupoffs,(xv>>16)*tileHeight,xv<<16,tileHeight,yv,0L);
+ else
+ msetupspritevline(palookupoffs,(xv>>16)*tileHeight,xv<<16,tileHeight,yv,0L);
+ }
+ else
+ {
+ tsetupspritevline(palookupoffs,(xv>>16)*tileHeight,xv<<16,tileHeight,yv);
+
+ if (dastat&32)
+ settrans(TRANS_REVERSE);
+ else
+ settrans(TRANS_NORMAL);
+ }
+
+ for(x=x1; x<x2; x++)
+ {
+ bx += xv2;
+ by += yv2;
+
+ y1 = uplc[x];
+ y2 = dplc[x];
+ if ((dastat&8) == 0)
+ {
+ if (startumost[x] > y1) y1 = startumost[x];
+ if (startdmost[x] < y2) y2 = startdmost[x];
+ }
+ if (y2 <= y1) continue;
+
+ switch(y1-oy)
+ {
+ case -1:
+ bx -= xv;
+ by -= yv;
+ oy = y1;
+ break;
+ case 0:
+ break;
+ case 1:
+ bx += xv;
+ by += yv;
+ oy = y1;
+ break;
+ default:
+ bx += xv*(y1-oy);
+ by += yv*(y1-oy);
+ oy = y1;
+ break;
+ }
+
+ p = ylookup[y1]+x+frameplace;
+
+ if ((dastat&1) == 0)
+ {
+ if (dastat&64)
+ spritevline(0L,by<<16,y2-y1+1,bx<<16,(bx>>16)*tileHeight+(by>>16)+bufplc,p);
+ else
+ mspritevline(0L,by<<16,y2-y1+1,bx<<16,(bx>>16)*tileHeight+(by>>16)+bufplc,p);
+ }
+ else
+ {
+ DrawSpriteVerticalLine(by<<16,y2-y1+1,bx<<16,(bx>>16)*tileHeight+(by>>16)+bufplc,p);
+ transarea += (y2-y1);
+ }
+ faketimerhandler();
+ }
+ }
+
+ if ((vidoption == 1) && (dastat&128) && (origbuffermode == 0))
+ {
+ buffermode = obuffermode;
+
+ }
+}
+
+
+void nextpage(void)
+{
+ int32_t i;
+ permfifotype *per;
+
+ if (qsetmode == 200)
+ {
+ for(i=permtail; i!=permhead; i=((i+1)&(MAXPERMS-1)))
+ {
+ per = &permfifo[i];
+ if ((per->pagesleft > 0) && (per->pagesleft <= numpages))
+ dorotatesprite(per->sx,per->sy,per->z,per->a,per->picnum,per->dashade,per->dapalnum,per->dastat,per->cx1,per->cy1,per->cx2,per->cy2);
+ }
+ } /* if */
+
+ _nextpage(); /* video driver specific. */
+
+
+ if (qsetmode == 200)
+ {
+ for(i=permtail; i!=permhead; i=((i+1)&(MAXPERMS-1)))
+ {
+ per = &permfifo[i];
+ if (per->pagesleft >= 130)
+ dorotatesprite(per->sx,per->sy,per->z,per->a,per->picnum,
+ per->dashade,per->dapalnum,per->dastat,
+ per->cx1,per->cy1,per->cx2,per->cy2);
+ if (per->pagesleft&127) per->pagesleft--;
+ if (((per->pagesleft&127) == 0) && (i == permtail))
+ permtail = ((permtail+1)&(MAXPERMS-1));
+ }
+ } /* if */
+
+ faketimerhandler();
+
+ if ((totalclock >= lastageclock+8) || (totalclock < lastageclock))
+ {
+ lastageclock = totalclock;
+ agecache();
+ }
+
+ beforedrawrooms = 1;
+ numframes++;
+ rb->yield();
+}
+
+
+
+int clipinsidebox(int32_t x, int32_t y, short wallnum, int32_t walldist)
+{
+ walltype *wal;
+ int32_t x1, y1, x2, y2, r;
+
+ r = (walldist<<1);
+ wal = &wall[wallnum];
+ x1 = wal->x+walldist-x;
+ y1 = wal->y+walldist-y;
+ wal = &wall[wal->point2];
+ x2 = wal->x+walldist-x;
+ y2 = wal->y+walldist-y;
+
+ if ((x1 < 0) && (x2 < 0)) return(0);
+ if ((y1 < 0) && (y2 < 0)) return(0);
+ if ((x1 >= r) && (x2 >= r)) return(0);
+ if ((y1 >= r) && (y2 >= r)) return(0);
+
+ x2 -= x1;
+ y2 -= y1;
+ if (x2*(walldist-y1) >= y2*(walldist-x1)) /* Front */
+ {
+ if (x2 > 0) x2 *= (0-y1);
+ else x2 *= (r-y1);
+ if (y2 > 0) y2 *= (r-x1);
+ else y2 *= (0-x1);
+ return(x2 < y2);
+ }
+ if (x2 > 0) x2 *= (r-y1);
+ else x2 *= (0-y1);
+ if (y2 > 0) y2 *= (0-x1);
+ else y2 *= (r-x1);
+ return((x2 >= y2)<<1);
+}
+
+static int clipinsideboxline(int32_t x, int32_t y, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t walldist)
+{
+ int32_t r;
+
+ r = (walldist<<1);
+
+ x1 += walldist-x;
+ x2 += walldist-x;
+ if ((x1 < 0) && (x2 < 0)) return(0);
+ if ((x1 >= r) && (x2 >= r)) return(0);
+
+ y1 += walldist-y;
+ y2 += walldist-y;
+ if ((y1 < 0) && (y2 < 0)) return(0);
+ if ((y1 >= r) && (y2 >= r)) return(0);
+
+ x2 -= x1;
+ y2 -= y1;
+ if (x2*(walldist-y1) >= y2*(walldist-x1)) /* Front */
+ {
+ if (x2 > 0) x2 *= (0-y1);
+ else x2 *= (r-y1);
+ if (y2 > 0) y2 *= (r-x1);
+ else y2 *= (0-x1);
+ return(x2 < y2);
+ }
+ if (x2 > 0) x2 *= (r-y1);
+ else x2 *= (0-y1);
+ if (y2 > 0) y2 *= (0-x1);
+ else y2 *= (r-x1);
+ return((x2 >= y2)<<1);
+}
+
+
+void drawline256 (int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t col)
+{
+ int32_t dx, dy, i, j, inc, plc, daend;
+ uint8_t* p;
+ col = palookup[0][col];
+
+ dx = x2-x1;
+ dy = y2-y1;
+ if (dx >= 0)
+ {
+ if ((x1 >= wx2) || (x2 < wx1)) return;
+ if (x1 < wx1) y1 += scale(wx1-x1,dy,dx), x1 = wx1;
+ if (x2 > wx2) y2 += scale(wx2-x2,dy,dx), x2 = wx2;
+ }
+ else
+ {
+ if ((x2 >= wx2) || (x1 < wx1)) return;
+ if (x2 < wx1) y2 += scale(wx1-x2,dy,dx), x2 = wx1;
+ if (x1 > wx2) y1 += scale(wx2-x1,dy,dx), x1 = wx2;
+ }
+ if (dy >= 0)
+ {
+ if ((y1 >= wy2) || (y2 < wy1)) return;
+ if (y1 < wy1) x1 += scale(wy1-y1,dx,dy), y1 = wy1;
+ if (y2 > wy2) x2 += scale(wy2-y2,dx,dy), y2 = wy2;
+ }
+ else
+ {
+ if ((y2 >= wy2) || (y1 < wy1)) return;
+ if (y2 < wy1) x2 += scale(wy1-y2,dx,dy), y2 = wy1;
+ if (y1 > wy2) x1 += scale(wy2-y1,dx,dy), y1 = wy2;
+ }
+
+ if (klabs(dx) >= klabs(dy))
+ {
+ if (dx == 0) return;
+ if (dx < 0)
+ {
+ i = x1;
+ x1 = x2;
+ x2 = i;
+ i = y1;
+ y1 = y2;
+ y2 = i;
+ }
+
+ inc = divscale12(dy,dx);
+ plc = y1+mulscale12((2047-x1)&4095,inc);
+ i = ((x1+2048)>>12);
+ daend = ((x2+2048)>>12);
+ for(; i<daend; i++)
+ {
+ j = (plc>>12);
+ if ((j >= startumost[i]) && (j < startdmost[i]))
+ drawpixel(ylookup[j]+i+frameplace,col);
+ plc += inc;
+ }
+ }
+ else
+ {
+ if (dy < 0)
+ {
+ i = x1;
+ x1 = x2;
+ x2 = i;
+ i = y1;
+ y1 = y2;
+ y2 = i;
+ }
+
+ inc = divscale12(dx,dy);
+ plc = x1+mulscale12((2047-y1)&4095,inc);
+ i = ((y1+2048)>>12);
+ daend = ((y2+2048)>>12);
+ p = ylookup[i]+frameplace;
+ for(; i<daend; i++)
+ {
+ j = (plc>>12);
+ if ((i >= startumost[j]) && (i < startdmost[j]))
+ drawpixel(j+p,col);
+ plc += inc;
+ p += ylookup[1];
+ }
+ }
+}
+
+/*
+ FCS: Return true if the point (x,Y) is inside the sector sectnum.
+ Note that a sector is closed (but can be concave) so the answer is always 0 or 1.
+
+ Algorithm: This is an optimized raycasting inside polygon test:
+ http://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm
+ The goal is to follow an ***horizontal*** ray passing by (x,y) and count how many
+ wall are being crossed.
+ If it is an odd number of time: (x,y) is inside the sector.
+ If it is an even nymber of time:(x,y) is outside the sector.
+ */
+
+int inside(int32_t x, int32_t y, short sectnum)
+{
+ walltype *wal;
+ int32_t i, x1, y1, x2, y2;
+ uint32_t wallCrossed;
+
+ //Quick check if the sector ID is valid.
+ if ((sectnum < 0) || (sectnum >= numsectors)) return(-1);
+
+ wallCrossed = 0;
+ wal = &wall[sector[sectnum].wallptr];
+ i = sector[sectnum].wallnum;
+ do
+ {
+ y1 = wal->y-y;
+ y2 = wall[wal->point2].y-y;
+
+ // Compare the sign of y1 and y2.
+ // If (y1^y2) < 0 : y1 and y2 have different sign bit: y is between wal->y and wall[wal->point2].y.
+ // The goal is to not take into consideration any wall that is totally above or totally under the point [x,y].
+ if ((y1^y2) < 0)
+ {
+ x1 = wal->x-x;
+ x2 = wall[wal->point2].x-x;
+
+ //If (x1^x2) >= 0 x1 and x2 have identic sign bit: x is on the left or the right of both wal->x and wall[wal->point2].x.
+ if ((x1^x2) >= 0)
+ {
+ // If (x,y) is totally on the left or on the right, just count x1 (which indicate if we are on
+ // on the left or on the right.
+ wallCrossed ^= x1;
+ }
+ else
+ {
+ // This is the most complicated case: X is between x1 and x2, we need a fine grained test.
+ // We need to know exactly if it is on the left or on the right in order to know if the ray
+ // is crossing the wall or not,
+ // The sign of the Cross-Product can answer this case :) !
+ wallCrossed ^= (x1*y2-x2*y1)^y2;
+ }
+ }
+
+ wal++;
+ i--;
+
+ } while (i);
+
+ //Just return the sign. If the position vector cut the sector walls an odd number of time
+ //it is inside. Otherwise (even) it is outside.
+ return(wallCrossed>>31);
+}
+
+
+int getangle(int32_t xvect, int32_t yvect)
+{
+ if ((xvect|yvect) == 0)
+ return(0);
+ if (xvect == 0)
+ return(512+((yvect<0)<<10));
+ if (yvect == 0)
+ return(((xvect<0)<<10));
+ if (xvect == yvect)
+ return(256+((xvect<0)<<10));
+ if (xvect == -yvect)
+ return(768+((xvect>0)<<10));
+ if (klabs(xvect) > klabs(yvect))
+ return(((radarang[640+scale(160,yvect,xvect)]>>6)+((xvect<0)<<10))&2047);
+
+ return(((radarang[640-scale(160,xvect,yvect)]>>6)+512+((yvect<0)<<10))&2047);
+}
+
+
+int ksqrt(int32_t num)
+{
+ return(nsqrtasm(num));
+}
+
+
+
+
+
+static void drawmaskwall(short damaskwallcnt)
+{
+ int32_t i, j, k, x, z, sectnum, z1, z2, lx, rx;
+ sectortype *sec, *nsec;
+ walltype *wal;
+
+ //Retrive pvWall ID.
+ z = maskwall[damaskwallcnt];
+
+ //Retrive world wall ID.
+ wal = &wall[pvWalls[z].worldWallId];
+
+ //Retrive sector ID
+ sectnum = pvWalls[z].sectorId;
+
+ //Retrive sector.
+ sec = &sector[sectnum];
+
+ //Retrive next sector.
+ nsec = &sector[wal->nextsector];
+
+ z1 = max(nsec->ceilingz,sec->ceilingz);
+ z2 = min(nsec->floorz,sec->floorz);
+
+ wallmost(uwall,z,sectnum,(uint8_t )0);
+ wallmost(uplc,z,(int32_t)wal->nextsector,(uint8_t )0);
+ for(x=pvWalls[z].screenSpaceCoo[0][VEC_COL]; x<=pvWalls[z].screenSpaceCoo[1][VEC_COL]; x++)
+ if (uplc[x] > uwall[x])
+ uwall[x] = uplc[x];
+
+ wallmost(dwall,z,sectnum,(uint8_t )1);
+ wallmost(dplc,z,(int32_t)wal->nextsector,(uint8_t )1);
+ for(x=pvWalls[z].screenSpaceCoo[0][VEC_COL]; x<=pvWalls[z].screenSpaceCoo[1][VEC_COL]; x++)
+ if (dplc[x] < dwall[x])
+ dwall[x] = dplc[x];
+
+
+ prepwall(z,wal);
+
+ globalorientation = (int32_t)wal->cstat;
+ globalpicnum = wal->overpicnum;
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
+ globalpicnum = 0;
+ globalxpanning = (int32_t)wal->xpanning;
+ globalypanning = (int32_t)wal->ypanning;
+
+ if (tiles[globalpicnum].animFlags&192)
+ globalpicnum += animateoffs(globalpicnum);
+
+ globalshade = (int32_t)wal->shade;
+ globvis = globalvisibility;
+ if (sec->visibility != 0)
+ globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+ globalpal = (int32_t)wal->pal;
+ globalshiftval = (picsiz[globalpicnum]>>4);
+ if (pow2long[globalshiftval] != tiles[globalpicnum].dim.height)
+ globalshiftval++;
+
+ globalshiftval = 32-globalshiftval;
+ globalyscale = (wal->yrepeat<<(globalshiftval-19));
+ if ((globalorientation&4) == 0)
+ globalzd = (((globalposz-z1)*globalyscale)<<8);
+ else
+ globalzd = (((globalposz-z2)*globalyscale)<<8);
+ globalzd += (globalypanning<<24);
+ if (globalorientation&256) globalyscale = -globalyscale, globalzd = -globalzd;
+
+ for(i=smostwallcnt-1; i>=0; i--)
+ {
+ j = smostwall[i];
+ if ((pvWalls[j].screenSpaceCoo[0][VEC_COL] > pvWalls[z].screenSpaceCoo[1][VEC_COL]) || (pvWalls[j].screenSpaceCoo[1][VEC_COL] < pvWalls[z].screenSpaceCoo[0][VEC_COL])) continue;
+ if (wallfront(j,z)) continue;
+
+ lx = max(pvWalls[j].screenSpaceCoo[0][VEC_COL],pvWalls[z].screenSpaceCoo[0][VEC_COL]);
+ rx = min(pvWalls[j].screenSpaceCoo[1][VEC_COL],pvWalls[z].screenSpaceCoo[1][VEC_COL]);
+
+ switch(smostwalltype[i])
+ {
+ case 0:
+ if (lx <= rx)
+ {
+ if ((lx == pvWalls[z].screenSpaceCoo[0][VEC_COL]) && (rx == pvWalls[z].screenSpaceCoo[1][VEC_COL])) return;
+ clearbufbyte(&dwall[lx],(rx-lx+1)*sizeof(dwall[0]),0L);
+ }
+ break;
+ case 1:
+ k = smoststart[i] - pvWalls[j].screenSpaceCoo[0][VEC_COL];
+ for(x=lx; x<=rx; x++)
+ if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
+ break;
+ case 2:
+ k = smoststart[i] - pvWalls[j].screenSpaceCoo[0][VEC_COL];
+ for(x=lx; x<=rx; x++)
+ if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
+ break;
+ }
+ }
+
+ /* maskwall */
+ if ((searchit >= 1) && (searchx >= pvWalls[z].screenSpaceCoo[0][VEC_COL]) && (searchx <= pvWalls[z].screenSpaceCoo[1][VEC_COL]))
+ if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
+ {
+ searchsector = sectnum;
+ searchwall = pvWalls[z].worldWallId;
+ searchstat = 4;
+ searchit = 1;
+ }
+
+ if ((globalorientation&128) == 0)
+ maskwallscan(pvWalls[z].screenSpaceCoo[0][VEC_COL],pvWalls[z].screenSpaceCoo[1][VEC_COL],uwall,dwall,swall,lwall);
+ else
+ {
+ if (globalorientation&128)
+ {
+ if (globalorientation&512)
+ settrans(TRANS_REVERSE);
+ else
+ settrans(TRANS_NORMAL);
+ }
+ transmaskwallscan(pvWalls[z].screenSpaceCoo[0][VEC_COL],pvWalls[z].screenSpaceCoo[1][VEC_COL]);
+ }
+}
+
+
+
+
+
+static void ceilspritehline (int32_t x2, int32_t y)
+{
+ int32_t x1, v, bx, by;
+
+ /*
+ * x = x1 + (x2-x1)t + (y1-y2)u x = 160v
+ * y = y1 + (y2-y1)t + (x2-x1)u y = (scrx-160)v
+ * z = z1 = z2 z = posz + (scry-horiz)v
+ */
+
+ x1 = lastx[y];
+ if (x2 < x1) return;
+
+ v = mulscale20(globalzd,horizlookup[y-globalhoriz+horizycent]);
+ bx = mulscale14(globalx2*x1+globalx1,v) + globalxpanning;
+ by = mulscale14(globaly2*x1+globaly1,v) + globalypanning;
+ asm1 = mulscale14(globalx2,v);
+ asm2 = mulscale14(globaly2,v);
+
+ asm3 = (int32_t)FP_OFF(palookup[globalpal]) + (getpalookup((int32_t)mulscale28(klabs(v),globvis),globalshade)<<8);
+
+ if ((globalorientation&2) == 0)
+ mhline(globalbufplc,bx,(x2-x1)<<16,0L,by,ylookup[y]+x1+frameoffset);
+ else
+ {
+ thline(globalbufplc,bx,(x2-x1)<<16,0L,by,ylookup[y]+x1+frameoffset);
+ transarea += (x2-x1);
+ }
+}
+
+
+static void ceilspritescan (int32_t x1, int32_t x2)
+{
+ int32_t x, y1, y2, twall, bwall;
+
+ y1 = uwall[x1];
+ y2 = y1;
+ for(x=x1; x<=x2; x++)
+ {
+ twall = uwall[x]-1;
+ bwall = dwall[x];
+ if (twall < bwall-1)
+ {
+ if (twall >= y2)
+ {
+ while (y1 < y2-1) ceilspritehline(x-1,++y1);
+ y1 = twall;
+ }
+ else
+ {
+ while (y1 < twall) ceilspritehline(x-1,++y1);
+ while (y1 > twall) lastx[y1--] = x;
+ }
+ while (y2 > bwall) ceilspritehline(x-1,--y2);
+ while (y2 < bwall) lastx[y2++] = x;
+ }
+ else
+ {
+ while (y1 < y2-1) ceilspritehline(x-1,++y1);
+ if (x == x2) break;
+ y1 = uwall[x+1];
+ y2 = y1;
+ }
+ }
+ while (y1 < y2-1) ceilspritehline(x2,++y1);
+ faketimerhandler();
+}
+
+static void drawsprite (int32_t snum)
+{
+ spritetype *tspr;
+ sectortype *sec;
+ int32_t startum, startdm, sectnum, xb, yp, cstat;
+ int32_t siz, xsiz, ysiz, xoff, yoff;
+ dimensions_t spriteDim;
+ int32_t x1, y1, x2, y2, lx, rx, dalx2, darx2, i, j, k, x, linum, linuminc;
+ int32_t yinc, z, z1, z2, xp1, yp1, xp2, yp2;
+ int32_t xv, yv, top, topinc, bot, botinc, hplc, hinc;
+ int32_t cosang, sinang, dax, day, lpoint, lmax, rpoint, rmax, dax1, dax2, y;
+ int32_t npoints, npoints2, zz, t, zsgn, zzsgn;
+ short tilenum, spritenum;
+ uint8_t swapped, daclip;
+
+ tspr = tspriteptr[snum];
+
+ xb = spritesx[snum];
+ yp = spritesy[snum];
+ tilenum = tspr->picnum;
+ spritenum = tspr->owner;
+ cstat = tspr->cstat;
+
+ if ((cstat&48) != 48)
+ {
+ if (tiles[tilenum].animFlags&192)
+ tilenum += animateoffs(tilenum);
+
+ if ((tiles[tilenum].dim.width <= 0) || (tiles[tilenum].dim.height <= 0) || (spritenum < 0))
+ return;
+ }
+ if ((tspr->xrepeat <= 0) || (tspr->yrepeat <= 0)) return;
+
+ sectnum = tspr->sectnum;
+ sec = &sector[sectnum];
+ globalpal = tspr->pal;
+ // FIX_00088: crash on maps using a bad palette index (like the end of roch3.map)
+ if (!palookup[globalpal])
+ globalpal = 0; // seem to crash when globalpal > 25
+ globalshade = tspr->shade;
+ if (cstat&2)
+ {
+
+ if (cstat&512)
+ settrans(TRANS_REVERSE);
+ else
+ settrans(TRANS_NORMAL);
+ }
+
+ xoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>8)&255))+((int32_t)tspr->xoffset);
+ yoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>16)&255))+((int32_t)tspr->yoffset);
+
+ if ((cstat&48) == 0)
+ {
+ if (yp <= (4<<8))
+ return;
+
+ siz = divscale19(xdimenscale,yp);
+
+ xv = mulscale16(((int32_t)tspr->xrepeat)<<16,xyaspect);
+
+ spriteDim.width = tiles[tilenum].dim.width;
+ spriteDim.height = tiles[tilenum].dim.height;
+
+ xsiz = mulscale30(siz,xv * spriteDim.width);
+ ysiz = mulscale14(siz,tspr->yrepeat * spriteDim.height);
+
+ if (((tiles[tilenum].dim.width>>11) >= xsiz) || (spriteDim.height >= (ysiz>>1)))
+ return; /* Watch out for divscale overflow */
+
+ x1 = xb-(xsiz>>1);
+ if (spriteDim.width & 1)
+ x1 += mulscale31(siz,xv); /* Odd xspans */
+ i = mulscale30(siz,xv*xoff);
+ if ((cstat&4) == 0)
+ x1 -= i;
+ else
+ x1 += i;
+
+ y1 = mulscale16(tspr->z-globalposz,siz);
+ y1 -= mulscale14(siz,tspr->yrepeat*yoff);
+ y1 += (globalhoriz<<8)-ysiz;
+ if (cstat&128)
+ {
+ y1 += (ysiz>>1);
+ if (spriteDim.height&1) y1 += mulscale15(siz,tspr->yrepeat); /* Odd yspans */
+ }
+
+ x2 = x1+xsiz-1;
+ y2 = y1+ysiz-1;
+ if ((y1|255) >= (y2|255)) return;
+
+ lx = (x1>>8)+1;
+ if (lx < 0) lx = 0;
+ rx = (x2>>8);
+ if (rx >= xdimen) rx = xdimen-1;
+ if (lx > rx) return;
+
+ yinc = divscale32(spriteDim.height,ysiz);
+
+ if ((sec->ceilingstat&3) == 0)
+ startum = globalhoriz+mulscale24(siz,sec->ceilingz-globalposz)-1;
+ else
+ startum = 0;
+
+ if ((sec->floorstat&3) == 0)
+ startdm = globalhoriz+mulscale24(siz,sec->floorz-globalposz)+1;
+ else
+ startdm = 0x7fffffff;
+
+ if ((y1>>8) > startum) startum = (y1>>8);
+ if ((y2>>8) < startdm) startdm = (y2>>8);
+
+ if (startum < -32768) startum = -32768;
+ if (startdm > 32767) startdm = 32767;
+ if (startum >= startdm) return;
+
+ if ((cstat&4) == 0)
+ {
+ linuminc = divscale24(spriteDim.width,xsiz);
+ linum = mulscale8((lx<<8)-x1,linuminc);
+ }
+ else
+ {
+ linuminc = -divscale24(spriteDim.width,xsiz);
+ linum = mulscale8((lx<<8)-x2,linuminc);
+ }
+ if ((cstat&8) > 0)
+ {
+ yinc = -yinc;
+ i = y1;
+ y1 = y2;
+ y2 = i;
+ }
+
+ for(x=lx; x<=rx; x++)
+ {
+ uwall[x] = max(startumost[x+windowx1]-windowy1,(short)startum);
+ dwall[x] = min(startdmost[x+windowx1]-windowy1,(short)startdm);
+ }
+ daclip = 0;
+ for(i=smostwallcnt-1; i>=0; i--)
+ {
+ if (smostwalltype[i]&daclip)
+ continue;
+
+ j = smostwall[i];
+ if ((pvWalls[j].screenSpaceCoo[0][VEC_COL] > rx) || (pvWalls[j].screenSpaceCoo[1][VEC_COL] < lx))
+ continue;
+
+ if ((yp <= pvWalls[j].screenSpaceCoo[0][VEC_DIST]) && (yp <= pvWalls[j].screenSpaceCoo[1][VEC_DIST]))
+ continue;
+
+ if (spritewallfront(tspr,pvWalls[j].worldWallId) && ((yp <= pvWalls[j].screenSpaceCoo[0][VEC_DIST]) || (yp <= pvWalls[j].screenSpaceCoo[1][VEC_DIST])))
+ continue;
+
+ dalx2 = max(pvWalls[j].screenSpaceCoo[0][VEC_COL],lx);
+ darx2 = min(pvWalls[j].screenSpaceCoo[1][VEC_COL],rx);
+
+ switch(smostwalltype[i])
+ {
+ case 0:
+ if (dalx2 <= darx2)
+ {
+ if ((dalx2 == lx) && (darx2 == rx))
+ return;
+ clearbufbyte(&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
+ }
+ break;
+ case 1:
+ k = smoststart[i] - pvWalls[j].screenSpaceCoo[0][VEC_COL];
+ for(x=dalx2; x<=darx2; x++)
+ if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
+ if ((dalx2 == lx) && (darx2 == rx)) daclip |= 1;
+ break;
+ case 2:
+ k = smoststart[i] - pvWalls[j].screenSpaceCoo[0][VEC_COL];
+ for(x=dalx2; x<=darx2; x++)
+ if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
+ if ((dalx2 == lx) && (darx2 == rx)) daclip |= 2;
+ break;
+ }
+ }
+
+ if (uwall[rx] >= dwall[rx])
+ {
+ for(x=lx; x<rx; x++)
+ if (uwall[x] < dwall[x]) break;
+ if (x == rx) return;
+ }
+
+ /* sprite */
+ if ((searchit >= 1) && (searchx >= lx) && (searchx <= rx))
+ if ((searchy >= uwall[searchx]) && (searchy < dwall[searchx]))
+ {
+ searchsector = sectnum;
+ searchwall = spritenum;
+ searchstat = 3;
+ searchit = 1;
+ }
+
+ z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
+ if (cstat&128)
+ {
+ z2 += ((spriteDim.height*tspr->yrepeat)<<1);
+ if (spriteDim.height&1) z2 += (tspr->yrepeat<<1); /* Odd yspans */
+ }
+ z1 = z2 - ((spriteDim.height*tspr->yrepeat)<<2);
+
+ globalorientation = 0;
+ globalpicnum = tilenum;
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
+ globalxpanning = 0L;
+ globalypanning = 0L;
+ globvis = globalvisibility;
+ if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+ globalshiftval = (picsiz[globalpicnum]>>4);
+ if (pow2long[globalshiftval] != tiles[globalpicnum].dim.height)
+ globalshiftval++;
+
+ globalshiftval = 32-globalshiftval;
+ globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
+ globalzd = (((globalposz-z1)*globalyscale)<<8);
+ if ((cstat&8) > 0)
+ {
+ globalyscale = -globalyscale;
+ globalzd = (((globalposz-z2)*globalyscale)<<8);
+ }
+
+ qinterpolatedown16((int32_t *)&lwall[lx],rx-lx+1,linum,linuminc);
+ clearbuf(&swall[lx],rx-lx+1,mulscale19(yp,xdimscale));
+
+ if ((cstat&2) == 0)
+ maskwallscan(lx,rx,uwall,dwall,swall,lwall);
+ else
+ transmaskwallscan(lx,rx);
+ }
+ else if ((cstat&48) == 16)
+ {
+ if ((cstat&4) > 0) xoff = -xoff;
+ if ((cstat&8) > 0) yoff = -yoff;
+
+ spriteDim.width = tiles[tilenum].dim.width;
+ spriteDim.height = tiles[tilenum].dim.height;
+
+ xv = tspr->xrepeat*sintable[(tspr->ang+2560+1536)&2047];
+ yv = tspr->xrepeat*sintable[(tspr->ang+2048+1536)&2047];
+ i = (spriteDim.width >>1)+xoff;
+ x1 = tspr->x-globalposx-mulscale16(xv,i);
+ x2 = x1+mulscale16(xv,spriteDim.width );
+ y1 = tspr->y-globalposy-mulscale16(yv,i);
+ y2 = y1+mulscale16(yv,spriteDim.width );
+
+ yp1 = dmulscale6(x1,cosviewingrangeglobalang,y1,sinviewingrangeglobalang);
+ yp2 = dmulscale6(x2,cosviewingrangeglobalang,y2,sinviewingrangeglobalang);
+ if ((yp1 <= 0) && (yp2 <= 0)) return;
+ xp1 = dmulscale6(y1,cosglobalang,-x1,singlobalang);
+ xp2 = dmulscale6(y2,cosglobalang,-x2,singlobalang);
+
+ x1 += globalposx;
+ y1 += globalposy;
+ x2 += globalposx;
+ y2 += globalposy;
+
+ swapped = 0;
+ if (dmulscale32(xp1,yp2,-xp2,yp1) >= 0) /* If wall's NOT facing you */
+ {
+ if ((cstat&64) != 0) return;
+ i = xp1, xp1 = xp2, xp2 = i;
+ i = yp1, yp1 = yp2, yp2 = i;
+ i = x1, x1 = x2, x2 = i;
+ i = y1, y1 = y2, y2 = i;
+ swapped = 1;
+ }
+
+ if (xp1 >= -yp1)
+ {
+ if (xp1 > yp1) return;
+
+ if (yp1 == 0) return;
+ pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL] = halfxdimen + scale(xp1,halfxdimen,yp1);
+ if (xp1 >= 0) pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]++; /* Fix for SIGNED divide */
+ if (pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL] >= xdimen) pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL] = xdimen-1;
+ pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_DIST] = yp1;
+ }
+ else
+ {
+ if (xp2 < -yp2) return;
+ pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL] = 0;
+ i = yp1-yp2+xp1-xp2;
+ if (i == 0) return;
+ pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_DIST] = yp1 + scale(yp2-yp1,xp1+yp1,i);
+ }
+ if (xp2 <= yp2)
+ {
+ if (xp2 < -yp2) return;
+
+ if (yp2 == 0) return;
+ pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL] = halfxdimen + scale(xp2,halfxdimen,yp2) - 1;
+ if (xp2 >= 0) pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]++; /* Fix for SIGNED divide */
+ if (pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL] >= xdimen) pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL] = xdimen-1;
+ pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_DIST] = yp2;
+ }
+ else
+ {
+ if (xp1 > yp1) return;
+
+ pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL] = xdimen-1;
+ i = xp2-xp1+yp1-yp2;
+ if (i == 0) return;
+ pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_DIST] = yp1 + scale(yp2-yp1,yp1-xp1,i);
+ }
+
+ if ((pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_DIST] < 256) || (pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_DIST] < 256) || (pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL] > pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]))
+ return;
+
+ topinc = -mulscale10(yp1,spriteDim.width);
+ top = (((mulscale10(xp1,xdimen) - mulscale9(pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]-halfxdimen,yp1))*spriteDim.width)>>3);
+ botinc = ((yp2-yp1)>>8);
+ bot = mulscale11(xp1-xp2,xdimen) + mulscale2(pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]-halfxdimen,botinc);
+
+ j = pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]+3;
+ z = mulscale20(top,krecipasm(bot));
+ lwall[pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]] = (z>>8);
+ for(x=pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]+4; x<=j; x+=4)
+ {
+ top += topinc;
+ bot += botinc;
+ zz = z;
+ z = mulscale20(top,krecipasm(bot));
+ lwall[x] = (z>>8);
+ i = ((z+zz)>>1);
+ lwall[x-2] = (i>>8);
+ lwall[x-3] = ((i+zz)>>9);
+ lwall[x-1] = ((i+z)>>9);
+ }
+
+ if (lwall[pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]] < 0) lwall[pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]] = 0;
+ if (lwall[pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]] >= spriteDim.width) lwall[pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]] = spriteDim.width-1;
+
+ if ((swapped^((cstat&4)>0)) > 0)
+ {
+ j = spriteDim.width-1;
+ for(x=pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]; x<=pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]; x++)
+ lwall[x] = j-lwall[x];
+ }
+
+ pvWalls[MAXWALLSB-1].cameraSpaceCoo[0][VEC_X] = xp1 ;
+ pvWalls[MAXWALLSB-1].cameraSpaceCoo[0][VEC_Y] = yp1 ;
+ pvWalls[MAXWALLSB-1].cameraSpaceCoo[1][VEC_X] = xp2 ;
+ pvWalls[MAXWALLSB-1].cameraSpaceCoo[1][VEC_Y] = yp2 ;
+
+
+ hplc = divscale19(xdimenscale,pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_DIST]);
+ hinc = divscale19(xdimenscale,pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_DIST]);
+ hinc = (hinc-hplc)/(pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]-pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]+1);
+
+ z2 = tspr->z - ((yoff*tspr->yrepeat)<<2);
+ if (cstat&128)
+ {
+ z2 += ((spriteDim.height*tspr->yrepeat)<<1);
+ if (spriteDim.height&1) z2 += (tspr->yrepeat<<1); /* Odd yspans */
+ }
+ z1 = z2 - ((spriteDim.height*tspr->yrepeat)<<2);
+
+ globalorientation = 0;
+ globalpicnum = tilenum;
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
+ globalxpanning = 0L;
+ globalypanning = 0L;
+ globvis = globalvisibility;
+ if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+ globalshiftval = (picsiz[globalpicnum]>>4);
+ if (pow2long[globalshiftval] != tiles[globalpicnum].dim.height) globalshiftval++;
+ globalshiftval = 32-globalshiftval;
+ globalyscale = divscale(512,tspr->yrepeat,globalshiftval-19);
+ globalzd = (((globalposz-z1)*globalyscale)<<8);
+ if ((cstat&8) > 0)
+ {
+ globalyscale = -globalyscale;
+ globalzd = (((globalposz-z2)*globalyscale)<<8);
+ }
+
+ if (((sec->ceilingstat&1) == 0) && (z1 < sec->ceilingz))
+ z1 = sec->ceilingz;
+ if (((sec->floorstat&1) == 0) && (z2 > sec->floorz))
+ z2 = sec->floorz;
+
+ owallmost(uwall,(int32_t)(MAXWALLSB-1),z1-globalposz);
+ owallmost(dwall,(int32_t)(MAXWALLSB-1),z2-globalposz);
+ for(i=pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]; i<=pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]; i++)
+ {
+ swall[i] = (krecipasm(hplc)<<2);
+ hplc += hinc;
+ }
+
+ for(i=smostwallcnt-1; i>=0; i--)
+ {
+ j = smostwall[i];
+
+ if ((pvWalls[j].screenSpaceCoo[0][VEC_COL] > pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]) || (pvWalls[j].screenSpaceCoo[1][VEC_COL] < pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL])) continue;
+
+ dalx2 = pvWalls[j].screenSpaceCoo[0][VEC_COL];
+ darx2 = pvWalls[j].screenSpaceCoo[1][VEC_COL];
+ if (max(pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_DIST],pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_DIST]) > min(pvWalls[j].screenSpaceCoo[0][VEC_DIST],pvWalls[j].screenSpaceCoo[1][VEC_DIST]))
+ {
+ if (min(pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_DIST],pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_DIST]) > max(pvWalls[j].screenSpaceCoo[0][VEC_DIST],pvWalls[j].screenSpaceCoo[1][VEC_DIST]))
+ {
+ x = 0x80000000;
+ }
+ else
+ {
+ x = pvWalls[j].worldWallId;
+ xp1 = wall[x].x;
+ yp1 = wall[x].y;
+ x = wall[x].point2;
+ xp2 = wall[x].x;
+ yp2 = wall[x].y;
+
+ z1 = (xp2-xp1)*(y1-yp1) - (yp2-yp1)*(x1-xp1);
+ z2 = (xp2-xp1)*(y2-yp1) - (yp2-yp1)*(x2-xp1);
+ if ((z1^z2) >= 0)
+ x = (z1+z2);
+ else
+ {
+ z1 = (x2-x1)*(yp1-y1) - (y2-y1)*(xp1-x1);
+ z2 = (x2-x1)*(yp2-y1) - (y2-y1)*(xp2-x1);
+
+ if ((z1^z2) >= 0)
+ x = -(z1+z2);
+ else
+ {
+ if ((xp2-xp1)*(tspr->y-yp1) == (tspr->x-xp1)*(yp2-yp1))
+ {
+ if (wall[pvWalls[j].worldWallId].nextsector == tspr->sectnum)
+ x = 0x80000000;
+ else
+ x = 0x7fffffff;
+ }
+ else
+ { /* INTERSECTION! */
+ x = (xp1-globalposx) + scale(xp2-xp1,z1,z1-z2);
+ y = (yp1-globalposy) + scale(yp2-yp1,z1,z1-z2);
+
+ yp1 = dmulscale14(x,cosglobalang,y,singlobalang);
+ if (yp1 > 0)
+ {
+ xp1 = dmulscale14(y,cosglobalang,-x,singlobalang);
+
+ x = halfxdimen + scale(xp1,halfxdimen,yp1);
+ if (xp1 >= 0) x++; /* Fix for SIGNED divide */
+
+ if (z1 < 0)
+ {
+ if (dalx2 < x) dalx2 = x;
+ }
+ else
+ {
+ if (darx2 > x) darx2 = x;
+ }
+ x = 0x80000001;
+ }
+ else
+ x = 0x7fffffff;
+ }
+ }
+ }
+ }
+ if (x < 0)
+ {
+ if (dalx2 < pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]) dalx2 = pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL];
+ if (darx2 > pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]) darx2 = pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL];
+ switch(smostwalltype[i])
+ {
+ case 0:
+ if (dalx2 <= darx2)
+ {
+ if ((dalx2 == pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]) && (darx2 == pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL])) return;
+ clearbufbyte(&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
+ }
+ break;
+ case 1:
+ k = smoststart[i] - pvWalls[j].screenSpaceCoo[0][VEC_COL];
+ for(x=dalx2; x<=darx2; x++)
+ if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
+ break;
+ case 2:
+ k = smoststart[i] - pvWalls[j].screenSpaceCoo[0][VEC_COL];
+ for(x=dalx2; x<=darx2; x++)
+ if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
+ break;
+ }
+ }
+ }
+ }
+
+ /* sprite */
+ if ((searchit >= 1) && (searchx >= pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL]) && (searchx <= pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]))
+ if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
+ {
+ searchsector = sectnum;
+ searchwall = spritenum;
+ searchstat = 3;
+ searchit = 1;
+ }
+
+ if ((cstat&2) == 0)
+ maskwallscan(pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL],pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL],uwall,dwall,swall,lwall);
+ else
+ transmaskwallscan(pvWalls[MAXWALLSB-1].screenSpaceCoo[0][VEC_COL],pvWalls[MAXWALLSB-1].screenSpaceCoo[1][VEC_COL]);
+ }
+ else if ((cstat&48) == 32)
+ {
+ if ((cstat&64) != 0)
+ if ((globalposz > tspr->z) == ((cstat&8)==0))
+ return;
+
+ if ((cstat&4) > 0) xoff = -xoff;
+ if ((cstat&8) > 0) yoff = -yoff;
+ spriteDim.width = tiles[tilenum].dim.width;
+ spriteDim.height = tiles[tilenum].dim.height;
+
+ /* Rotate center point */
+ dax = tspr->x-globalposx;
+ day = tspr->y-globalposy;
+ rzi[0] = dmulscale10(cosglobalang,dax,singlobalang,day);
+ rxi[0] = dmulscale10(cosglobalang,day,-singlobalang,dax);
+
+ /* Get top-left corner */
+ i = ((tspr->ang+2048-globalang)&2047);
+ cosang = sintable[(i+512)&2047];
+ sinang = sintable[i];
+ dax = ((spriteDim.width>>1)+xoff)*tspr->xrepeat;
+ day = ((spriteDim.height>>1)+yoff)*tspr->yrepeat;
+ rzi[0] += dmulscale12(sinang,dax,cosang,day);
+ rxi[0] += dmulscale12(sinang,day,-cosang,dax);
+
+ /* Get other 3 corners */
+ dax = spriteDim.width*tspr->xrepeat;
+ day = spriteDim.height*tspr->yrepeat;
+ rzi[1] = rzi[0]-mulscale12(sinang,dax);
+ rxi[1] = rxi[0]+mulscale12(cosang,dax);
+ dax = -mulscale12(cosang,day);
+ day = -mulscale12(sinang,day);
+ rzi[2] = rzi[1]+dax;
+ rxi[2] = rxi[1]+day;
+ rzi[3] = rzi[0]+dax;
+ rxi[3] = rxi[0]+day;
+
+ /* Put all points on same z */
+ ryi[0] = scale((tspr->z-globalposz),yxaspect,320<<8);
+ if (ryi[0] == 0) return;
+ ryi[1] = ryi[2] = ryi[3] = ryi[0];
+
+ if ((cstat&4) == 0)
+ {
+ z = 0;
+ z1 = 1;
+ z2 = 3;
+ }
+ else
+ {
+ z = 1;
+ z1 = 0;
+ z2 = 2;
+ }
+
+ dax = rzi[z1]-rzi[z];
+ day = rxi[z1]-rxi[z];
+ bot = dmulscale8(dax,dax,day,day);
+ if (((klabs(dax)>>13) >= bot) || ((klabs(day)>>13) >= bot)) return;
+ globalx1 = divscale18(dax,bot);
+ globalx2 = divscale18(day,bot);
+
+ dax = rzi[z2]-rzi[z];
+ day = rxi[z2]-rxi[z];
+ bot = dmulscale8(dax,dax,day,day);
+ if (((klabs(dax)>>13) >= bot) || ((klabs(day)>>13) >= bot)) return;
+ globaly1 = divscale18(dax,bot);
+ globaly2 = divscale18(day,bot);
+
+ /* Calculate globals for hline texture mapping function */
+ globalxpanning = (rxi[z]<<12);
+ globalypanning = (rzi[z]<<12);
+ globalzd = (ryi[z]<<12);
+
+ rzi[0] = mulscale16(rzi[0],viewingrange);
+ rzi[1] = mulscale16(rzi[1],viewingrange);
+ rzi[2] = mulscale16(rzi[2],viewingrange);
+ rzi[3] = mulscale16(rzi[3],viewingrange);
+
+ if (ryi[0] < 0) /* If ceilsprite is above you, reverse order of points */
+ {
+ i = rxi[1];
+ rxi[1] = rxi[3];
+ rxi[3] = i;
+ i = rzi[1];
+ rzi[1] = rzi[3];
+ rzi[3] = i;
+ }
+
+
+ /* Clip polygon in 3-space */
+ npoints = 4;
+
+ /* Clip edge 1 */
+ npoints2 = 0;
+ zzsgn = rxi[0]+rzi[0];
+ for(z=0; z<npoints; z++)
+ {
+ zz = z+1;
+ if (zz == npoints) zz = 0;
+ zsgn = zzsgn;
+ zzsgn = rxi[zz]+rzi[zz];
+ if (zsgn >= 0)
+ {
+ rxi2[npoints2] = rxi[z];
+ ryi2[npoints2] = ryi[z];
+ rzi2[npoints2] = rzi[z];
+ npoints2++;
+ }
+ if ((zsgn^zzsgn) < 0)
+ {
+ t = divscale30(zsgn,zsgn-zzsgn);
+ rxi2[npoints2] = rxi[z] + mulscale30(t,rxi[zz]-rxi[z]);
+ ryi2[npoints2] = ryi[z] + mulscale30(t,ryi[zz]-ryi[z]);
+ rzi2[npoints2] = rzi[z] + mulscale30(t,rzi[zz]-rzi[z]);
+ npoints2++;
+ }
+ }
+ if (npoints2 <= 2) return;
+
+ /* Clip edge 2 */
+ npoints = 0;
+ zzsgn = rxi2[0]-rzi2[0];
+ for(z=0; z<npoints2; z++)
+ {
+ zz = z+1;
+ if (zz == npoints2) zz = 0;
+ zsgn = zzsgn;
+ zzsgn = rxi2[zz]-rzi2[zz];
+ if (zsgn <= 0)
+ {
+ rxi[npoints] = rxi2[z];
+ ryi[npoints] = ryi2[z];
+ rzi[npoints] = rzi2[z];
+ npoints++;
+ }
+ if ((zsgn^zzsgn) < 0)
+ {
+ t = divscale30(zsgn,zsgn-zzsgn);
+ rxi[npoints] = rxi2[z] + mulscale30(t,rxi2[zz]-rxi2[z]);
+ ryi[npoints] = ryi2[z] + mulscale30(t,ryi2[zz]-ryi2[z]);
+ rzi[npoints] = rzi2[z] + mulscale30(t,rzi2[zz]-rzi2[z]);
+ npoints++;
+ }
+ }
+ if (npoints <= 2) return;
+
+ /* Clip edge 3 */
+ npoints2 = 0;
+ zzsgn = ryi[0]*halfxdimen + (rzi[0]*(globalhoriz-0));
+ for(z=0; z<npoints; z++)
+ {
+ zz = z+1;
+ if (zz == npoints) zz = 0;
+ zsgn = zzsgn;
+ zzsgn = ryi[zz]*halfxdimen + (rzi[zz]*(globalhoriz-0));
+ if (zsgn >= 0)
+ {
+ rxi2[npoints2] = rxi[z];
+ ryi2[npoints2] = ryi[z];
+ rzi2[npoints2] = rzi[z];
+ npoints2++;
+ }
+ if ((zsgn^zzsgn) < 0)
+ {
+ t = divscale30(zsgn,zsgn-zzsgn);
+ rxi2[npoints2] = rxi[z] + mulscale30(t,rxi[zz]-rxi[z]);
+ ryi2[npoints2] = ryi[z] + mulscale30(t,ryi[zz]-ryi[z]);
+ rzi2[npoints2] = rzi[z] + mulscale30(t,rzi[zz]-rzi[z]);
+ npoints2++;
+ }
+ }
+ if (npoints2 <= 2) return;
+
+ /* Clip edge 4 */
+ npoints = 0;
+ zzsgn = ryi2[0]*halfxdimen + (rzi2[0]*(globalhoriz-ydimen));
+ for(z=0; z<npoints2; z++)
+ {
+ zz = z+1;
+ if (zz == npoints2) zz = 0;
+ zsgn = zzsgn;
+ zzsgn = ryi2[zz]*halfxdimen + (rzi2[zz]*(globalhoriz-ydimen));
+ if (zsgn <= 0)
+ {
+ rxi[npoints] = rxi2[z];
+ ryi[npoints] = ryi2[z];
+ rzi[npoints] = rzi2[z];
+ npoints++;
+ }
+ if ((zsgn^zzsgn) < 0)
+ {
+ t = divscale30(zsgn,zsgn-zzsgn);
+ rxi[npoints] = rxi2[z] + mulscale30(t,rxi2[zz]-rxi2[z]);
+ ryi[npoints] = ryi2[z] + mulscale30(t,ryi2[zz]-ryi2[z]);
+ rzi[npoints] = rzi2[z] + mulscale30(t,rzi2[zz]-rzi2[z]);
+ npoints++;
+ }
+ }
+ if (npoints <= 2) return;
+
+ /* Project onto screen */
+ lpoint = -1;
+ lmax = 0x7fffffff;
+ rpoint = -1;
+ rmax = 0x80000000;
+ for(z=0; z<npoints; z++)
+ {
+ xsi[z] = scale(rxi[z],xdimen<<15,rzi[z]) + (xdimen<<15);
+ ysi[z] = scale(ryi[z],xdimen<<15,rzi[z]) + (globalhoriz<<16);
+ if (xsi[z] < 0) xsi[z] = 0;
+ if (xsi[z] > (xdimen<<16)) xsi[z] = (xdimen<<16);
+ if (ysi[z] < ((int32_t)0<<16)) ysi[z] = ((int32_t)0<<16);
+ if (ysi[z] > ((int32_t)ydimen<<16)) ysi[z] = ((int32_t)ydimen<<16);
+ if (xsi[z] < lmax) lmax = xsi[z], lpoint = z;
+ if (xsi[z] > rmax) rmax = xsi[z], rpoint = z;
+ }
+
+ /* Get uwall arrays */
+ for(z=lpoint; z!=rpoint; z=zz)
+ {
+ zz = z+1;
+ if (zz == npoints) zz = 0;
+
+ dax1 = ((xsi[z]+65535)>>16);
+ dax2 = ((xsi[zz]+65535)>>16);
+ if (dax2 > dax1)
+ {
+ yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
+ y = ysi[z] + mulscale16((dax1<<16)-xsi[z],yinc);
+ qinterpolatedown16short((int32_t *)(&uwall[dax1]),dax2-dax1,y,yinc);
+ }
+ }
+
+ /* Get dwall arrays */
+ for(; z!=lpoint; z=zz)
+ {
+ zz = z+1;
+ if (zz == npoints) zz = 0;
+
+ dax1 = ((xsi[zz]+65535)>>16);
+ dax2 = ((xsi[z]+65535)>>16);
+ if (dax2 > dax1)
+ {
+ yinc = divscale16(ysi[zz]-ysi[z],xsi[zz]-xsi[z]);
+ y = ysi[zz] + mulscale16((dax1<<16)-xsi[zz],yinc);
+ qinterpolatedown16short((int32_t *)(&dwall[dax1]),dax2-dax1,y,yinc);
+ }
+ }
+
+
+ lx = ((lmax+65535)>>16);
+ rx = ((rmax+65535)>>16);
+ for(x=lx; x<=rx; x++)
+ {
+ uwall[x] = max(uwall[x],startumost[x+windowx1]-windowy1);
+ dwall[x] = min(dwall[x],startdmost[x+windowx1]-windowy1);
+ }
+
+ /* Additional uwall/dwall clipping goes here */
+ for(i=smostwallcnt-1; i>=0; i--)
+ {
+ j = smostwall[i];
+ if ((pvWalls[j].screenSpaceCoo[0][VEC_COL] > rx) || (pvWalls[j].screenSpaceCoo[1][VEC_COL] < lx)) continue;
+ if ((yp <= pvWalls[j].screenSpaceCoo[0][VEC_DIST]) && (yp <= pvWalls[j].screenSpaceCoo[1][VEC_DIST])) continue;
+
+ /* if (spritewallfront(tspr,thewall[j]) == 0) */
+ x = pvWalls[j].worldWallId;
+ xp1 = wall[x].x;
+ yp1 = wall[x].y;
+ x = wall[x].point2;
+ xp2 = wall[x].x;
+ yp2 = wall[x].y;
+ x = (xp2-xp1)*(tspr->y-yp1)-(tspr->x-xp1)*(yp2-yp1);
+ if ((yp > pvWalls[j].screenSpaceCoo[0][VEC_DIST]) && (yp > pvWalls[j].screenSpaceCoo[1][VEC_DIST])) x = -1;
+ if ((x >= 0) && ((x != 0) || (wall[pvWalls[j].worldWallId].nextsector != tspr->sectnum))) continue;
+
+ dalx2 = max(pvWalls[j].screenSpaceCoo[0][VEC_COL],lx);
+ darx2 = min(pvWalls[j].screenSpaceCoo[1][VEC_COL],rx);
+
+ switch(smostwalltype[i])
+ {
+ case 0:
+ if (dalx2 <= darx2)
+ {
+ if ((dalx2 == lx) && (darx2 == rx)) return;
+ clearbufbyte(&dwall[dalx2],(darx2-dalx2+1)*sizeof(dwall[0]),0L);
+ }
+ break;
+ case 1:
+ k = smoststart[i] - pvWalls[j].screenSpaceCoo[0][VEC_COL];
+ for(x=dalx2; x<=darx2; x++)
+ if (smost[k+x] > uwall[x]) uwall[x] = smost[k+x];
+ break;
+ case 2:
+ k = smoststart[i] - pvWalls[j].screenSpaceCoo[0][VEC_COL];
+ for(x=dalx2; x<=darx2; x++)
+ if (smost[k+x] < dwall[x]) dwall[x] = smost[k+x];
+ break;
+ }
+ }
+
+ /* sprite */
+ if ((searchit >= 1) && (searchx >= lx) && (searchx <= rx))
+ if ((searchy >= uwall[searchx]) && (searchy <= dwall[searchx]))
+ {
+ searchsector = sectnum;
+ searchwall = spritenum;
+ searchstat = 3;
+ searchit = 1;
+ }
+
+ globalorientation = cstat;
+ globalpicnum = tilenum;
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
+ globalpicnum = 0;
+
+ TILE_MakeAvailable(globalpicnum);
+
+ setgotpic(globalpicnum);
+ globalbufplc = tiles[globalpicnum].data;
+
+ globvis = mulscale16(globalhisibility,viewingrange);
+ if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+
+ x = picsiz[globalpicnum];
+ y = ((x>>4)&15);
+ x &= 15;
+ if (pow2long[x] != spriteDim.width)
+ {
+ x++;
+ globalx1 = mulscale(globalx1,spriteDim.width,x);
+ globalx2 = mulscale(globalx2,spriteDim.width,x);
+ }
+
+ dax = globalxpanning;
+ day = globalypanning;
+ globalxpanning = -dmulscale6(globalx1,day,globalx2,dax);
+ globalypanning = -dmulscale6(globaly1,day,globaly2,dax);
+
+ globalx2 = mulscale16(globalx2,viewingrange);
+ globaly2 = mulscale16(globaly2,viewingrange);
+ globalzd = mulscale16(globalzd,viewingrangerecip);
+
+ globalx1 = (globalx1-globalx2)*halfxdimen;
+ globaly1 = (globaly1-globaly2)*halfxdimen;
+
+ if ((cstat&2) == 0)
+ msethlineshift(x,y);
+ else
+ tsethlineshift(x,y);
+
+ /* Draw it! */
+ ceilspritescan(lx,rx-1);
+ }
+
+ if (automapping == 1) show2dsprite[spritenum>>3] |= pow2char[spritenum&7];
+}
+
+/*
+ FCS: Draw every transparent sprites in Back To Front Order. Also draw decals on the walls...
+ */
+void drawmasks(void)
+{
+ int32_t i, j, k, l, gap, xs, ys, xp, yp, yoff, yspan;
+ /* int32_t zs, zp; */
+
+ //Copy sprite address in a sprite proxy structure (pointers are easier to re-arrange than structs).
+ for(i=spritesortcnt-1; i>=0; i--)
+ tspriteptr[i] = &tsprite[i];
+
+
+ //Generate screenspace coordinate (X column and Y distance).
+ for(i=spritesortcnt-1; i>=0; i--)
+ {
+ //Translate and rotate the sprite in Camera space coordinate.
+ xs = tspriteptr[i]->x-globalposx;
+ ys = tspriteptr[i]->y-globalposy;
+ yp = dmulscale6(xs,cosviewingrangeglobalang,ys,sinviewingrangeglobalang);
+
+ if (yp > (4<<8))
+ {
+ xp = dmulscale6(ys,cosglobalang,-xs,singlobalang);
+ spritesx[i] = scale(xp+yp,xdimen<<7,yp);
+ }
+ else if ((tspriteptr[i]->cstat&48) == 0)
+ {
+ spritesortcnt--; /* Delete face sprite if on wrong side! */
+ //Move the sprite at the end of the array and decrease array length.
+ if (i != spritesortcnt)
+ {
+ tspriteptr[i] = tspriteptr[spritesortcnt];
+ spritesx[i] = spritesx[spritesortcnt];
+ spritesy[i] = spritesy[spritesortcnt];
+ }
+ continue;
+ }
+ spritesy[i] = yp;
+ }
+
+ //FCS: Bubble sort ?! REally ?!?!?
+ gap = 1;
+ while (gap < spritesortcnt) gap = (gap<<1)+1;
+ for(gap>>=1; gap>0; gap>>=1) /* Sort sprite list */
+ for(i=0; i<spritesortcnt-gap; i++)
+ for(l=i; l>=0; l-=gap)
+ {
+ if (spritesy[l] <= spritesy[l+gap])
+ break;
+
+ swaplong((int32_t *)&tspriteptr[l],(int32_t *)&tspriteptr[l+gap]);
+ swaplong(&spritesx[l],&spritesx[l+gap]);
+ swaplong(&spritesy[l],&spritesy[l+gap]);
+ }
+
+ if (spritesortcnt > 0)
+ spritesy[spritesortcnt] = (spritesy[spritesortcnt-1]^1);
+
+ ys = spritesy[0];
+ i = 0;
+ for(j=1; j<=spritesortcnt; j++)
+ {
+ if (spritesy[j] == ys)
+ continue;
+
+ ys = spritesy[j];
+ if (j > i+1)
+ {
+ for(k=i; k<j; k++)
+ {
+ spritesz[k] = tspriteptr[k]->z;
+ if ((tspriteptr[k]->cstat&48) != 32)
+ {
+ yoff = (int32_t)((int8_t )((tiles[tspriteptr[k]->picnum].animFlags>>16)&255))+((int32_t)tspriteptr[k]->yoffset);
+ spritesz[k] -= ((yoff*tspriteptr[k]->yrepeat)<<2);
+ yspan = (tiles[tspriteptr[k]->picnum].dim.height*tspriteptr[k]->yrepeat<<2);
+ if (!(tspriteptr[k]->cstat&128))
+ spritesz[k] -= (yspan>>1);
+ if (klabs(spritesz[k]-globalposz) < (yspan>>1))
+ spritesz[k] = globalposz;
+ }
+ }
+ for(k=i+1; k<j; k++)
+ for(l=i; l<k; l++)
+ if (klabs(spritesz[k]-globalposz) < klabs(spritesz[l]-globalposz))
+ {
+ swaplong((int32_t *)&tspriteptr[k],(int32_t *)&tspriteptr[l]);
+ swaplong(&spritesx[k],&spritesx[l]);
+ swaplong(&spritesy[k],&spritesy[l]);
+ swaplong(&spritesz[k],&spritesz[l]);
+ }
+ for(k=i+1; k<j; k++)
+ for(l=i; l<k; l++)
+ if (tspriteptr[k]->statnum < tspriteptr[l]->statnum)
+ {
+ swaplong((int32_t *)&tspriteptr[k],(int32_t *)&tspriteptr[l]);
+ swaplong(&spritesx[k],&spritesx[l]);
+ swaplong(&spritesy[k],&spritesy[l]);
+ }
+ }
+ i = j;
+ }
+
+ while ((spritesortcnt > 0) && (maskwallcnt > 0)) /* While BOTH > 0 */
+ {
+ j = maskwall[maskwallcnt-1];
+ if (spritewallfront(tspriteptr[spritesortcnt-1],pvWalls[j].worldWallId) == 0)
+ drawsprite(--spritesortcnt);
+ else
+ {
+ /* Check to see if any sprites behind the masked wall... */
+ k = -1;
+ gap = 0;
+ for(i=spritesortcnt-2; i>=0; i--)
+ if ((pvWalls[j].screenSpaceCoo[0][VEC_COL] <= (spritesx[i]>>8)) && ((spritesx[i]>>8) <= pvWalls[j].screenSpaceCoo[1][VEC_COL]))
+ if (spritewallfront(tspriteptr[i],pvWalls[j].worldWallId) == 0)
+ {
+ drawsprite(i);
+ tspriteptr[i]->owner = -1;
+ k = i;
+ gap++;
+ }
+ if (k >= 0) /* remove holes in sprite list */
+ {
+ for(i=k; i<spritesortcnt; i++)
+ if (tspriteptr[i]->owner >= 0)
+ {
+ if (i > k)
+ {
+ tspriteptr[k] = tspriteptr[i];
+ spritesx[k] = spritesx[i];
+ spritesy[k] = spritesy[i];
+ }
+ k++;
+ }
+ spritesortcnt -= gap;
+ }
+
+ /* finally safe to draw the masked wall */
+ drawmaskwall(--maskwallcnt);
+ }
+ }
+ while (spritesortcnt > 0) drawsprite(--spritesortcnt);
+ while (maskwallcnt > 0) drawmaskwall(--maskwallcnt);
+}
+
+
+int setsprite(short spritenum, int32_t newx, int32_t newy, int32_t newz)
+{
+ short tempsectnum;
+
+ sprite[spritenum].x = newx;
+ sprite[spritenum].y = newy;
+ sprite[spritenum].z = newz;
+
+ tempsectnum = sprite[spritenum].sectnum;
+ updatesector(newx,newy,&tempsectnum);
+ if (tempsectnum < 0)
+ return(-1);
+ if (tempsectnum != sprite[spritenum].sectnum)
+ changespritesect(spritenum,tempsectnum);
+
+ return(0);
+}
+
+
+void initspritelists(void)
+{
+ int32_t i;
+
+ for (i=0; i<MAXSECTORS; i++) /* Init doubly-linked sprite sector lists */
+ headspritesect[i] = -1;
+
+ headspritesect[MAXSECTORS] = 0;
+
+ for(i=0; i<MAXSPRITES; i++){
+ prevspritesect[i] = i-1;
+ nextspritesect[i] = i+1;
+ sprite[i].sectnum = MAXSECTORS;
+ }
+ prevspritesect[0] = -1;
+ nextspritesect[MAXSPRITES-1] = -1;
+
+
+ for(i=0; i<MAXSTATUS; i++) /* Init doubly-linked sprite status lists */
+ headspritestat[i] = -1;
+ headspritestat[MAXSTATUS] = 0;
+ for(i=0; i<MAXSPRITES; i++)
+ {
+ prevspritestat[i] = i-1;
+ nextspritestat[i] = i+1;
+ sprite[i].statnum = MAXSTATUS;
+ }
+ prevspritestat[0] = -1;
+ nextspritestat[MAXSPRITES-1] = -1;
+}
+
+
+int insertsprite(short sectnum, short statnum)
+{
+ insertspritestat(statnum);
+ return(insertspritesect(sectnum));
+}
+
+
+int insertspritesect(short sectnum)
+{
+ short blanktouse;
+
+ if ((sectnum >= MAXSECTORS) || (headspritesect[MAXSECTORS] == -1))
+ return(-1); /* list full */
+
+ blanktouse = headspritesect[MAXSECTORS];
+
+ headspritesect[MAXSECTORS] = nextspritesect[blanktouse];
+ if (headspritesect[MAXSECTORS] >= 0)
+ prevspritesect[headspritesect[MAXSECTORS]] = -1;
+
+ prevspritesect[blanktouse] = -1;
+ nextspritesect[blanktouse] = headspritesect[sectnum];
+ if (headspritesect[sectnum] >= 0)
+ prevspritesect[headspritesect[sectnum]] = blanktouse;
+ headspritesect[sectnum] = blanktouse;
+
+ sprite[blanktouse].sectnum = sectnum;
+
+ return(blanktouse);
+}
+
+
+int insertspritestat(short statnum)
+{
+ short blanktouse;
+
+ if ((statnum >= MAXSTATUS) || (headspritestat[MAXSTATUS] == -1))
+ return(-1); /* list full */
+
+ blanktouse = headspritestat[MAXSTATUS];
+
+ headspritestat[MAXSTATUS] = nextspritestat[blanktouse];
+ if (headspritestat[MAXSTATUS] >= 0)
+ prevspritestat[headspritestat[MAXSTATUS]] = -1;
+
+ prevspritestat[blanktouse] = -1;
+ nextspritestat[blanktouse] = headspritestat[statnum];
+ if (headspritestat[statnum] >= 0)
+ prevspritestat[headspritestat[statnum]] = blanktouse;
+ headspritestat[statnum] = blanktouse;
+
+ sprite[blanktouse].statnum = statnum;
+
+ return(blanktouse);
+}
+
+
+int deletesprite(short spritenum)
+{
+ deletespritestat(spritenum);
+ return(deletespritesect(spritenum));
+}
+
+
+int deletespritesect(short deleteme)
+{
+ if (sprite[deleteme].sectnum == MAXSECTORS)
+ return(-1);
+
+ if (headspritesect[sprite[deleteme].sectnum] == deleteme)
+ headspritesect[sprite[deleteme].sectnum] = nextspritesect[deleteme];
+
+ if (prevspritesect[deleteme] >= 0) nextspritesect[prevspritesect[deleteme]] = nextspritesect[deleteme];
+ if (nextspritesect[deleteme] >= 0) prevspritesect[nextspritesect[deleteme]] = prevspritesect[deleteme];
+
+ if (headspritesect[MAXSECTORS] >= 0) prevspritesect[headspritesect[MAXSECTORS]] = deleteme;
+ prevspritesect[deleteme] = -1;
+ nextspritesect[deleteme] = headspritesect[MAXSECTORS];
+ headspritesect[MAXSECTORS] = deleteme;
+
+ sprite[deleteme].sectnum = MAXSECTORS;
+ return(0);
+}
+
+
+int deletespritestat(short deleteme)
+{
+ if (sprite[deleteme].statnum == MAXSTATUS)
+ return(-1);
+
+ if (headspritestat[sprite[deleteme].statnum] == deleteme)
+ headspritestat[sprite[deleteme].statnum] = nextspritestat[deleteme];
+
+ if (prevspritestat[deleteme] >= 0) nextspritestat[prevspritestat[deleteme]] = nextspritestat[deleteme];
+ if (nextspritestat[deleteme] >= 0) prevspritestat[nextspritestat[deleteme]] = prevspritestat[deleteme];
+
+ if (headspritestat[MAXSTATUS] >= 0) prevspritestat[headspritestat[MAXSTATUS]] = deleteme;
+ prevspritestat[deleteme] = -1;
+ nextspritestat[deleteme] = headspritestat[MAXSTATUS];
+ headspritestat[MAXSTATUS] = deleteme;
+
+ sprite[deleteme].statnum = MAXSTATUS;
+ return(0);
+}
+
+
+int changespritesect(short spritenum, short newsectnum)
+{
+ if ((newsectnum < 0) || (newsectnum > MAXSECTORS)) return(-1);
+ if (sprite[spritenum].sectnum == newsectnum) return(0);
+ if (sprite[spritenum].sectnum == MAXSECTORS) return(-1);
+ if (deletespritesect(spritenum) < 0) return(-1);
+ insertspritesect(newsectnum);
+ return(0);
+}
+
+
+int changespritestat(short spritenum, short newstatnum)
+{
+ if ((newstatnum < 0) || (newstatnum > MAXSTATUS)) return(-1);
+ if (sprite[spritenum].statnum == newstatnum) return(0);
+ if (sprite[spritenum].statnum == MAXSTATUS) return(-1);
+ if (deletespritestat(spritenum) < 0) return(-1);
+ insertspritestat(newstatnum);
+ return(0);
+}
+
+
+int nextsectorneighborz(short sectnum, int32_t thez,
+ short topbottom, short direction)
+{
+ walltype *wal;
+ int32_t i, testz, nextz;
+ short sectortouse;
+
+ if (direction == 1) nextz = 0x7fffffff;
+ else nextz = 0x80000000;
+
+ sectortouse = -1;
+
+ wal = &wall[sector[sectnum].wallptr];
+ i = sector[sectnum].wallnum;
+ do
+ {
+ if (wal->nextsector >= 0)
+ {
+ if (topbottom == 1)
+ {
+ testz = sector[wal->nextsector].floorz;
+ if (direction == 1)
+ {
+ if ((testz > thez) && (testz < nextz))
+ {
+ nextz = testz;
+ sectortouse = wal->nextsector;
+ }
+ }
+ else
+ {
+ if ((testz < thez) && (testz > nextz))
+ {
+ nextz = testz;
+ sectortouse = wal->nextsector;
+ }
+ }
+ }
+ else
+ {
+ testz = sector[wal->nextsector].ceilingz;
+ if (direction == 1)
+ {
+ if ((testz > thez) && (testz < nextz))
+ {
+ nextz = testz;
+ sectortouse = wal->nextsector;
+ }
+ }
+ else
+ {
+ if ((testz < thez) && (testz > nextz))
+ {
+ nextz = testz;
+ sectortouse = wal->nextsector;
+ }
+ }
+ }
+ }
+ wal++;
+ i--;
+ } while (i != 0);
+
+ return(sectortouse);
+}
+
+
+int cansee(int32_t x1, int32_t y1, int32_t z1, short sect1,
+ int32_t x2, int32_t y2, int32_t z2, short sect2)
+{
+ sectortype *sec;
+ walltype *wal, *wal2;
+ int32_t i, cnt, nexts, x, y, z, cz, fz, dasectnum, dacnt, danum;
+ int32_t x21, y21, z21, x31, y31, x34, y34, bot, t;
+
+ if ((x1 == x2) && (y1 == y2))
+ return(sect1 == sect2);
+
+ x21 = x2-x1;
+ y21 = y2-y1;
+ z21 = z2-z1;
+
+ clipsectorlist[0] = sect1;
+ danum = 1;
+ for(dacnt=0; dacnt<danum; dacnt++)
+ {
+ dasectnum = clipsectorlist[dacnt];
+ sec = &sector[dasectnum];
+ for(cnt=sec->wallnum,wal=&wall[sec->wallptr]; cnt>0; cnt--,wal++)
+ {
+ wal2 = &wall[wal->point2];
+ x31 = wal->x-x1;
+ x34 = wal->x-wal2->x;
+ y31 = wal->y-y1;
+ y34 = wal->y-wal2->y;
+
+ bot = y21*x34-x21*y34;
+ if (bot <= 0)
+ continue;
+
+ t = y21*x31-x21*y31;
+ if ((uint32_t)t >= (uint32_t)bot)
+ continue;
+ t = y31*x34-x31*y34;
+ if ((uint32_t)t >= (uint32_t)bot)
+ continue;
+
+ nexts = wal->nextsector;
+ if ((nexts < 0) || (wal->cstat&32)) return(0);
+
+ t = divscale24(t,bot);
+ x = x1 + mulscale24(x21,t);
+ y = y1 + mulscale24(y21,t);
+ z = z1 + mulscale24(z21,t);
+
+ getzsofslope((short)dasectnum,x,y,&cz,&fz);
+ if ((z <= cz) || (z >= fz))
+ return(0);
+ getzsofslope((short)nexts,x,y,&cz,&fz);
+ if ((z <= cz) || (z >= fz))
+ return(0);
+
+ for(i=danum-1; i>=0; i--)
+ if (clipsectorlist[i] == nexts)
+ break;
+ if (i < 0)
+ clipsectorlist[danum++] = nexts;
+ }
+ }
+ for(i=danum-1; i>=0;i--)
+ if (clipsectorlist[i] == sect2)
+ return(1);
+ return(0);
+}
+
+
+int lintersect(int32_t x1, int32_t y1, int32_t z1, int32_t x2, int32_t y2, int32_t z2,
+ int32_t x3, int32_t y3, int32_t x4, int32_t y4, int32_t *intx,
+ int32_t *inty, int32_t *intz)
+{ /* p1 to p2 is a line segment */
+ int32_t x21, y21, x34, y34, x31, y31, bot, topt, topu, t;
+
+ x21 = x2-x1;
+ x34 = x3-x4;
+ y21 = y2-y1;
+ y34 = y3-y4;
+ bot = x21*y34 - y21*x34;
+ if (bot >= 0)
+ {
+ if (bot == 0) return(0);
+ x31 = x3-x1;
+ y31 = y3-y1;
+ topt = x31*y34 - y31*x34;
+ if ((topt < 0) || (topt >= bot)) return(0);
+ topu = x21*y31 - y21*x31;
+ if ((topu < 0) || (topu >= bot)) return(0);
+ }
+ else
+ {
+ x31 = x3-x1;
+ y31 = y3-y1;
+ topt = x31*y34 - y31*x34;
+ if ((topt > 0) || (topt <= bot)) return(0);
+ topu = x21*y31 - y21*x31;
+ if ((topu > 0) || (topu <= bot)) return(0);
+ }
+ t = divscale24(topt,bot);
+ *intx = x1 + mulscale24(x21,t);
+ *inty = y1 + mulscale24(y21,t);
+ *intz = z1 + mulscale24(z2-z1,t);
+ return(1);
+}
+
+
+int rintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx, int32_t vy, int32_t vz,
+ int32_t x3, int32_t y3, int32_t x4, int32_t y4, int32_t *intx,
+ int32_t *inty, int32_t *intz)
+{ /* p1 towards p2 is a ray */
+ int32_t x34, y34, x31, y31, bot, topt, topu, t;
+
+ x34 = x3-x4;
+ y34 = y3-y4;
+ bot = vx*y34 - vy*x34;
+ if (bot >= 0)
+ {
+ if (bot == 0) return(0);
+ x31 = x3-x1;
+ y31 = y3-y1;
+ topt = x31*y34 - y31*x34;
+ if (topt < 0) return(0);
+ topu = vx*y31 - vy*x31;
+ if ((topu < 0) || (topu >= bot)) return(0);
+ }
+ else
+ {
+ x31 = x3-x1;
+ y31 = y3-y1;
+ topt = x31*y34 - y31*x34;
+ if (topt > 0) return(0);
+ topu = vx*y31 - vy*x31;
+ if ((topu > 0) || (topu <= bot)) return(0);
+ }
+ t = divscale16(topt,bot);
+ *intx = x1 + mulscale16(vx,t);
+ *inty = y1 + mulscale16(vy,t);
+ *intz = z1 + mulscale16(vz,t);
+ return(1);
+}
+
+
+int hitscan(int32_t xs, int32_t ys, int32_t zs, short sectnum,
+ int32_t vx, int32_t vy, int32_t vz,
+ short *hitsect, short *hitwall, short *hitsprite,
+ int32_t *hitx, int32_t *hity, int32_t *hitz, uint32_t cliptype)
+{
+ sectortype *sec;
+ walltype *wal, *wal2;
+ spritetype *spr;
+ int32_t z, zz, x1, y1=0, z1=0, x2, y2, x3, y3, x4, y4, intx, inty, intz;
+ int32_t topt, topu, bot, dist, offx, offy, cstat;
+ int32_t i, j, k, l, tilenum, xoff, yoff, dax, day, daz, daz2;
+ int32_t ang, cosang, sinang, xspan, yspan, xrepeat, yrepeat;
+ int32_t dawalclipmask, dasprclipmask;
+ short tempshortcnt, tempshortnum, dasector, startwall, endwall;
+ short nextsector;
+ uint8_t clipyou;
+
+ *hitsect = -1;
+ *hitwall = -1;
+ *hitsprite = -1;
+ if (sectnum < 0) return(-1);
+
+ *hitx = hitscangoalx;
+ *hity = hitscangoaly;
+
+ dawalclipmask = (cliptype&65535);
+ dasprclipmask = (cliptype>>16);
+
+ clipsectorlist[0] = sectnum;
+ tempshortcnt = 0;
+ tempshortnum = 1;
+ do
+ {
+ dasector = clipsectorlist[tempshortcnt];
+ sec = &sector[dasector];
+
+ x1 = 0x7fffffff;
+ if (sec->ceilingstat&2)
+ {
+ wal = &wall[sec->wallptr];
+ wal2 = &wall[wal->point2];
+ dax = wal2->x-wal->x;
+ day = wal2->y-wal->y;
+ i = nsqrtasm(dax*dax+day*day);
+ if (i == 0) continue;
+ i = divscale15(sec->ceilingheinum,i);
+ dax *= i;
+ day *= i;
+
+ j = (vz<<8)-dmulscale15(dax,vy,-day,vx);
+ if (j != 0)
+ {
+ i = ((sec->ceilingz-zs)<<8)+dmulscale15(dax,ys-wal->y,-day,xs-wal->x);
+ if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j)))
+ {
+ i = divscale30(i,j);
+ x1 = xs + mulscale30(vx,i);
+ y1 = ys + mulscale30(vy,i);
+ z1 = zs + mulscale30(vz,i);
+ }
+ }
+ }
+ else if ((vz < 0) && (zs >= sec->ceilingz))
+ {
+ z1 = sec->ceilingz;
+ i = z1-zs;
+ if ((klabs(i)>>1) < -vz)
+ {
+ i = divscale30(i,vz);
+ x1 = xs + mulscale30(vx,i);
+ y1 = ys + mulscale30(vy,i);
+ }
+ }
+ if ((x1 != 0x7fffffff) && (klabs(x1-xs)+klabs(y1-ys) < klabs((*hitx)-xs)+klabs((*hity)-ys)))
+ if (inside(x1,y1,dasector) != 0)
+ {
+ *hitsect = dasector;
+ *hitwall = -1;
+ *hitsprite = -1;
+ *hitx = x1;
+ *hity = y1;
+ *hitz = z1;
+ }
+
+ x1 = 0x7fffffff;
+ if (sec->floorstat&2)
+ {
+ wal = &wall[sec->wallptr];
+ wal2 = &wall[wal->point2];
+ dax = wal2->x-wal->x;
+ day = wal2->y-wal->y;
+ i = nsqrtasm(dax*dax+day*day);
+ if (i == 0) continue;
+ i = divscale15(sec->floorheinum,i);
+ dax *= i;
+ day *= i;
+
+ j = (vz<<8)-dmulscale15(dax,vy,-day,vx);
+ if (j != 0)
+ {
+ i = ((sec->floorz-zs)<<8)+dmulscale15(dax,ys-wal->y,-day,xs-wal->x);
+ if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j)))
+ {
+ i = divscale30(i,j);
+ x1 = xs + mulscale30(vx,i);
+ y1 = ys + mulscale30(vy,i);
+ z1 = zs + mulscale30(vz,i);
+ }
+ }
+ }
+ else if ((vz > 0) && (zs <= sec->floorz))
+ {
+ z1 = sec->floorz;
+ i = z1-zs;
+ if ((klabs(i)>>1) < vz)
+ {
+ i = divscale30(i,vz);
+ x1 = xs + mulscale30(vx,i);
+ y1 = ys + mulscale30(vy,i);
+ }
+ }
+ if ((x1 != 0x7fffffff) && (klabs(x1-xs)+klabs(y1-ys) < klabs((*hitx)-xs)+klabs((*hity)-ys)))
+ if (inside(x1,y1,dasector) != 0)
+ {
+ *hitsect = dasector;
+ *hitwall = -1;
+ *hitsprite = -1;
+ *hitx = x1;
+ *hity = y1;
+ *hitz = z1;
+ }
+
+ startwall = sec->wallptr;
+ endwall = startwall + sec->wallnum;
+ for(z=startwall,wal=&wall[startwall]; z<endwall; z++,wal++)
+ {
+ wal2 = &wall[wal->point2];
+ x1 = wal->x;
+ y1 = wal->y;
+ x2 = wal2->x;
+ y2 = wal2->y;
+
+ if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
+ if (rintersect(xs,ys,zs,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz) == 0) continue;
+
+ if (klabs(intx-xs)+klabs(inty-ys) >= klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
+
+ nextsector = wal->nextsector;
+ if ((nextsector < 0) || (wal->cstat&dawalclipmask))
+ {
+ *hitsect = dasector;
+ *hitwall = z;
+ *hitsprite = -1;
+ *hitx = intx;
+ *hity = inty;
+ *hitz = intz;
+ continue;
+ }
+ getzsofslope(nextsector,intx,inty,&daz,&daz2);
+ if ((intz <= daz) || (intz >= daz2))
+ {
+ *hitsect = dasector;
+ *hitwall = z;
+ *hitsprite = -1;
+ *hitx = intx;
+ *hity = inty;
+ *hitz = intz;
+ continue;
+ }
+
+ for(zz=tempshortnum-1; zz>=0; zz--)
+ if (clipsectorlist[zz] == nextsector) break;
+ if (zz < 0) clipsectorlist[tempshortnum++] = nextsector;
+ }
+
+ for(z=headspritesect[dasector]; z>=0; z=nextspritesect[z])
+ {
+ spr = &sprite[z];
+ cstat = spr->cstat;
+ if ((cstat&dasprclipmask) == 0) continue;
+
+ x1 = spr->x;
+ y1 = spr->y;
+ z1 = spr->z;
+ switch(cstat&48)
+ {
+ case 0:
+ topt = vx*(x1-xs) + vy*(y1-ys);
+ if (topt <= 0) continue;
+ bot = vx*vx + vy*vy;
+ if (bot == 0) continue;
+
+ intz = zs+scale(vz,topt,bot);
+
+ i = (tiles[spr->picnum].dim.height*spr->yrepeat<<2);
+
+ if (cstat&128)
+ z1 += (i>>1);
+
+ if (tiles[spr->picnum].animFlags&0x00ff0000)
+ z1 -= ((int32_t)((int8_t )((tiles[spr->picnum].animFlags>>16)&255))*spr->yrepeat<<2);
+
+ if ((intz > z1) || (intz < z1-i)) continue;
+ topu = vx*(y1-ys) - vy*(x1-xs);
+
+ offx = scale(vx,topu,bot);
+ offy = scale(vy,topu,bot);
+ dist = offx*offx + offy*offy;
+ i = tiles[spr->picnum].dim.width*spr->xrepeat;
+ i *= i;
+ if (dist > (i>>7)) continue;
+ intx = xs + scale(vx,topt,bot);
+ inty = ys + scale(vy,topt,bot);
+
+ if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
+
+ *hitsect = dasector;
+ *hitwall = -1;
+ *hitsprite = z;
+ *hitx = intx;
+ *hity = inty;
+ *hitz = intz;
+ break;
+ case 16:
+ /*
+ * These lines get the 2 points of the rotated sprite
+ * Given: (x1, y1) starts out as the center point
+ */
+ tilenum = spr->picnum;
+ xoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>8)&255))+((int32_t)spr->xoffset);
+ if ((cstat&4) > 0) xoff = -xoff;
+ k = spr->ang;
+ l = spr->xrepeat;
+ dax = sintable[k&2047]*l;
+ day = sintable[(k+1536)&2047]*l;
+ l = tiles[tilenum].dim.width;
+ k = (l>>1)+xoff;
+ x1 -= mulscale16(dax,k);
+ x2 = x1+mulscale16(dax,l);
+ y1 -= mulscale16(day,k);
+ y2 = y1+mulscale16(day,l);
+
+ if ((cstat&64) != 0) /* back side of 1-way sprite */
+ if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
+
+ if (rintersect(xs,ys,zs,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz) == 0) continue;
+
+ if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
+
+ k = ((tiles[spr->picnum].dim.height*spr->yrepeat)<<2);
+ if (cstat&128)
+ daz = spr->z+(k>>1);
+ else
+ daz = spr->z;
+
+ if (tiles[spr->picnum].animFlags&0x00ff0000)
+ daz -= ((int32_t)((int8_t )((tiles[spr->picnum].animFlags>>16)&255))*spr->yrepeat<<2);
+
+ if ((intz < daz) && (intz > daz-k))
+ {
+ *hitsect = dasector;
+ *hitwall = -1;
+ *hitsprite = z;
+ *hitx = intx;
+ *hity = inty;
+ *hitz = intz;
+ }
+ break;
+ case 32:
+ if (vz == 0) continue;
+ intz = z1;
+ if (((intz-zs)^vz) < 0) continue;
+ if ((cstat&64) != 0)
+ if ((zs > intz) == ((cstat&8)==0)) continue;
+
+ intx = xs+scale(intz-zs,vx,vz);
+ inty = ys+scale(intz-zs,vy,vz);
+
+ if (klabs(intx-xs)+klabs(inty-ys) > klabs((*hitx)-xs)+klabs((*hity)-ys)) continue;
+
+ tilenum = spr->picnum;
+ xoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>8)&255))+((int32_t)spr->xoffset);
+ yoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>16)&255))+((int32_t)spr->yoffset);
+ if ((cstat&4) > 0) xoff = -xoff;
+ if ((cstat&8) > 0) yoff = -yoff;
+
+ ang = spr->ang;
+ cosang = sintable[(ang+512)&2047];
+ sinang = sintable[ang];
+ xspan = tiles[tilenum].dim.width;
+ xrepeat = spr->xrepeat;
+ yspan = tiles[tilenum].dim.height;
+ yrepeat = spr->yrepeat;
+
+ dax = ((xspan>>1)+xoff)*xrepeat;
+ day = ((yspan>>1)+yoff)*yrepeat;
+ x1 += dmulscale16(sinang,dax,cosang,day)-intx;
+ y1 += dmulscale16(sinang,day,-cosang,dax)-inty;
+ l = xspan*xrepeat;
+ x2 = x1 - mulscale16(sinang,l);
+ y2 = y1 + mulscale16(cosang,l);
+ l = yspan*yrepeat;
+ k = -mulscale16(cosang,l);
+ x3 = x2+k;
+ x4 = x1+k;
+ k = -mulscale16(sinang,l);
+ y3 = y2+k;
+ y4 = y1+k;
+
+ clipyou = 0;
+ if ((y1^y2) < 0)
+ {
+ if ((x1^x2) < 0) clipyou ^= (x1*y2<x2*y1)^(y1<y2);
+ else if (x1 >= 0) clipyou ^= 1;
+ }
+ if ((y2^y3) < 0)
+ {
+ if ((x2^x3) < 0) clipyou ^= (x2*y3<x3*y2)^(y2<y3);
+ else if (x2 >= 0) clipyou ^= 1;
+ }
+ if ((y3^y4) < 0)
+ {
+ if ((x3^x4) < 0) clipyou ^= (x3*y4<x4*y3)^(y3<y4);
+ else if (x3 >= 0) clipyou ^= 1;
+ }
+ if ((y4^y1) < 0)
+ {
+ if ((x4^x1) < 0) clipyou ^= (x4*y1<x1*y4)^(y4<y1);
+ else if (x4 >= 0) clipyou ^= 1;
+ }
+
+ if (clipyou != 0)
+ {
+ *hitsect = dasector;
+ *hitwall = -1;
+ *hitsprite = z;
+ *hitx = intx;
+ *hity = inty;
+ *hitz = intz;
+ }
+ break;
+ }
+ }
+ tempshortcnt++;
+ } while (tempshortcnt < tempshortnum);
+ return(0);
+}
+
+
+int neartag(int32_t xs, int32_t ys, int32_t zs, short sectnum, short ange,
+ short *neartagsector, short *neartagwall, short *neartagsprite,
+ int32_t *neartaghitdist, int32_t neartagrange, uint8_t tagsearch)
+{
+ walltype *wal, *wal2;
+ spritetype *spr;
+ int32_t i, z, zz, xe, ye, ze, x1, y1, z1, x2, y2, intx, inty, intz;
+ int32_t topt, topu, bot, dist, offx, offy, vx, vy, vz;
+ short tempshortcnt, tempshortnum, dasector, startwall, endwall;
+ short nextsector, good;
+
+ *neartagsector = -1;
+ *neartagwall = -1;
+ *neartagsprite = -1;
+ *neartaghitdist = 0;
+
+ if (sectnum < 0) return(0);
+ if ((tagsearch < 1) || (tagsearch > 3)) return(0);
+
+ vx = mulscale14(sintable[(ange+2560)&2047],neartagrange);
+ xe = xs+vx;
+ vy = mulscale14(sintable[(ange+2048)&2047],neartagrange);
+ ye = ys+vy;
+ vz = 0;
+ ze = 0;
+
+ clipsectorlist[0] = sectnum;
+ tempshortcnt = 0;
+ tempshortnum = 1;
+
+ do
+ {
+ dasector = clipsectorlist[tempshortcnt];
+
+ startwall = sector[dasector].wallptr;
+ endwall = startwall + sector[dasector].wallnum - 1;
+ for(z=startwall,wal=&wall[startwall]; z<=endwall; z++,wal++)
+ {
+ wal2 = &wall[wal->point2];
+ x1 = wal->x;
+ y1 = wal->y;
+ x2 = wal2->x;
+ y2 = wal2->y;
+
+ nextsector = wal->nextsector;
+
+ good = 0;
+ if (nextsector >= 0)
+ {
+ if ((tagsearch&1) && sector[nextsector].lotag) good |= 1;
+ if ((tagsearch&2) && sector[nextsector].hitag) good |= 1;
+ }
+ if ((tagsearch&1) && wal->lotag) good |= 2;
+ if ((tagsearch&2) && wal->hitag) good |= 2;
+
+ if ((good == 0) && (nextsector < 0)) continue;
+ if ((x1-xs)*(y2-ys) < (x2-xs)*(y1-ys)) continue;
+
+ if (lintersect(xs,ys,zs,xe,ye,ze,x1,y1,x2,y2,&intx,&inty,&intz) == 1)
+ {
+ if (good != 0)
+ {
+ if (good&1) *neartagsector = nextsector;
+ if (good&2) *neartagwall = z;
+ *neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]);
+ xe = intx;
+ ye = inty;
+ ze = intz;
+ }
+ if (nextsector >= 0)
+ {
+ for(zz=tempshortnum-1; zz>=0; zz--)
+ if (clipsectorlist[zz] == nextsector) break;
+ if (zz < 0) clipsectorlist[tempshortnum++] = nextsector;
+ }
+ }
+ }
+
+ for(z=headspritesect[dasector]; z>=0; z=nextspritesect[z])
+ {
+ spr = &sprite[z];
+
+ good = 0;
+ if ((tagsearch&1) && spr->lotag) good |= 1;
+ if ((tagsearch&2) && spr->hitag) good |= 1;
+ if (good != 0)
+ {
+ x1 = spr->x;
+ y1 = spr->y;
+ z1 = spr->z;
+
+ topt = vx*(x1-xs) + vy*(y1-ys);
+ if (topt > 0)
+ {
+ bot = vx*vx + vy*vy;
+ if (bot != 0)
+ {
+ intz = zs+scale(vz,topt,bot);
+ i = tiles[spr->picnum].dim.height*spr->yrepeat;
+ if (spr->cstat&128)
+ z1 += (i<<1);
+ if (tiles[spr->picnum].animFlags&0x00ff0000)
+ z1 -= ((int32_t)((int8_t )((tiles[spr->picnum].animFlags>>16)&255))*spr->yrepeat<<2);
+ if ((intz <= z1) && (intz >= z1-(i<<2)))
+ {
+ topu = vx*(y1-ys) - vy*(x1-xs);
+
+ offx = scale(vx,topu,bot);
+ offy = scale(vy,topu,bot);
+ dist = offx*offx + offy*offy;
+ i = (tiles[spr->picnum].dim.width*spr->xrepeat);
+ i *= i;
+ if (dist <= (i>>7))
+ {
+ intx = xs + scale(vx,topt,bot);
+ inty = ys + scale(vy,topt,bot);
+ if (klabs(intx-xs)+klabs(inty-ys) < klabs(xe-xs)+klabs(ye-ys))
+ {
+ *neartagsprite = z;
+ *neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]);
+ xe = intx;
+ ye = inty;
+ ze = intz;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ tempshortcnt++;
+ } while (tempshortcnt < tempshortnum);
+ return(0);
+}
+
+
+void dragpoint(short pointhighlight, int32_t dax, int32_t day)
+{
+ short cnt, tempshort;
+
+ wall[pointhighlight].x = dax;
+ wall[pointhighlight].y = day;
+
+ cnt = MAXWALLS;
+ tempshort = pointhighlight; /* search points CCW */
+ do
+ {
+ if (wall[tempshort].nextwall >= 0)
+ {
+ tempshort = wall[wall[tempshort].nextwall].point2;
+ wall[tempshort].x = dax;
+ wall[tempshort].y = day;
+ }
+ else
+ {
+ tempshort = pointhighlight; /* search points CW if not searched all the way around */
+ do
+ {
+ if (wall[lastwall(tempshort)].nextwall >= 0)
+ {
+ tempshort = wall[lastwall(tempshort)].nextwall;
+ wall[tempshort].x = dax;
+ wall[tempshort].y = day;
+ }
+ else
+ {
+ break;
+ }
+ cnt--;
+ }
+ while ((tempshort != pointhighlight) && (cnt > 0));
+ break;
+ }
+ cnt--;
+ }
+ while ((tempshort != pointhighlight) && (cnt > 0));
+}
+
+
+int lastwall(short point)
+{
+ int32_t i, j, cnt;
+
+ if ((point > 0) && (wall[point-1].point2 == point)) return(point-1);
+ i = point;
+ cnt = MAXWALLS;
+ do
+ {
+ j = wall[i].point2;
+ if (j == point) return(i);
+ i = j;
+ cnt--;
+ } while (cnt > 0);
+ return(point);
+}
+
+#define addclipline(dax1, day1, dax2, day2, daoval) \
+{ \
+clipit[clipnum].x1 = dax1; clipit[clipnum].y1 = day1; \
+clipit[clipnum].x2 = dax2; clipit[clipnum].y2 = day2; \
+clipobjectval[clipnum] = daoval; \
+clipnum++; \
+} \
+
+
+static void keepaway (int32_t *x, int32_t *y, int32_t w)
+{
+ int32_t dx, dy, ox, oy, x1, y1;
+ uint8_t first;
+
+ x1 = clipit[w].x1;
+ dx = clipit[w].x2-x1;
+ y1 = clipit[w].y1;
+ dy = clipit[w].y2-y1;
+ ox = ksgn(-dy);
+ oy = ksgn(dx);
+ first = (klabs(dx) <= klabs(dy));
+ while (1)
+ {
+ if (dx*(*y-y1) > (*x-x1)*dy) return;
+ if (first == 0) *x += ox;
+ else *y += oy;
+ first ^= 1;
+ }
+}
+
+
+static int raytrace(int32_t x3, int32_t y3, int32_t *x4, int32_t *y4)
+{
+ int32_t x1, y1, x2, y2, bot, topu, nintx, ninty, cnt, z, hitwall;
+ int32_t x21, y21, x43, y43;
+
+ hitwall = -1;
+ for(z=clipnum-1; z>=0; z--)
+ {
+ x1 = clipit[z].x1;
+ x2 = clipit[z].x2;
+ x21 = x2-x1;
+ y1 = clipit[z].y1;
+ y2 = clipit[z].y2;
+ y21 = y2-y1;
+
+ topu = x21*(y3-y1) - (x3-x1)*y21;
+ if (topu <= 0) continue;
+ if (x21*(*y4-y1) > (*x4-x1)*y21) continue;
+ x43 = *x4-x3;
+ y43 = *y4-y3;
+ if (x43*(y1-y3) > (x1-x3)*y43) continue;
+ if (x43*(y2-y3) <= (x2-x3)*y43) continue;
+ bot = x43*y21 - x21*y43;
+ if (bot == 0) continue;
+
+ cnt = 256;
+ do
+ {
+ cnt--;
+ if (cnt < 0) {
+ *x4 = x3;
+ *y4 = y3;
+ return(z);
+ }
+ nintx = x3 + scale(x43,topu,bot);
+ ninty = y3 + scale(y43,topu,bot);
+ topu--;
+ } while (x21*(ninty-y1) <= (nintx-x1)*y21);
+
+ if (klabs(x3-nintx)+klabs(y3-ninty) < klabs(x3-*x4)+klabs(y3-*y4))
+ {
+ *x4 = nintx;
+ *y4 = ninty;
+ hitwall = z;
+ }
+ }
+ return(hitwall);
+}
+
+
+/* !!! ugh...move this var into clipmove as a parameter, and update build2.txt! */
+int32_t clipmoveboxtracenum = 3;
+int clipmove (int32_t *x, int32_t *y, int32_t *z, short *sectnum,
+ int32_t xvect, int32_t yvect, int32_t walldist, int32_t ceildist,
+ int32_t flordist, uint32_t cliptype)
+{
+ walltype *wal, *wal2;
+ spritetype *spr;
+ sectortype *sec, *sec2;
+ int32_t i, j, templong1, templong2;
+ int32_t oxvect, oyvect, goalx, goaly, intx, inty, lx, ly, retval;
+ int32_t k, l, clipsectcnt, startwall, endwall, cstat, dasect;
+ int32_t x1, y1, x2, y2, cx, cy, rad, xmin, ymin, xmax, ymax, daz, daz2;
+ int32_t bsz, dax, day, xoff, yoff, xspan, yspan, cosang, sinang, tilenum;
+ int32_t xrepeat, yrepeat, gx, gy, dx, dy, dasprclipmask, dawalclipmask;
+ int32_t hitwall, cnt, clipyou;
+
+ if (((xvect|yvect) == 0) || (*sectnum < 0)) return(0);
+ retval = 0;
+
+ oxvect = xvect;
+ oyvect = yvect;
+
+ goalx = (*x) + (xvect>>14);
+ goaly = (*y) + (yvect>>14);
+
+
+ clipnum = 0;
+
+ cx = (((*x)+goalx)>>1);
+ cy = (((*y)+goaly)>>1);
+ /* Extra walldist for sprites on sector lines */
+ gx = goalx-(*x);
+ gy = goaly-(*y);
+ rad = nsqrtasm(gx*gx + gy*gy) + MAXCLIPDIST+walldist + 8;
+ xmin = cx-rad;
+ ymin = cy-rad;
+ xmax = cx+rad;
+ ymax = cy+rad;
+
+ dawalclipmask = (cliptype&65535); /* CLIPMASK0 = 0x00010001 */
+ dasprclipmask = (cliptype>>16); /* CLIPMASK1 = 0x01000040 */
+
+ clipsectorlist[0] = (*sectnum);
+ clipsectcnt = 0;
+ clipsectnum = 1;
+ do
+ {
+ dasect = clipsectorlist[clipsectcnt++];
+ sec = &sector[dasect];
+ startwall = sec->wallptr;
+ endwall = startwall + sec->wallnum;
+ for(j=startwall,wal=&wall[startwall]; j<endwall; j++,wal++)
+ {
+ wal2 = &wall[wal->point2];
+ if ((wal->x < xmin) && (wal2->x < xmin)) continue;
+ if ((wal->x > xmax) && (wal2->x > xmax)) continue;
+ if ((wal->y < ymin) && (wal2->y < ymin)) continue;
+ if ((wal->y > ymax) && (wal2->y > ymax)) continue;
+
+ x1 = wal->x;
+ y1 = wal->y;
+ x2 = wal2->x;
+ y2 = wal2->y;
+
+ dx = x2-x1;
+ dy = y2-y1;
+ if (dx*((*y)-y1) < ((*x)-x1)*dy) continue; /* If wall's not facing you */
+
+ if (dx > 0) dax = dx*(ymin-y1);
+ else dax = dx*(ymax-y1);
+ if (dy > 0) day = dy*(xmax-x1);
+ else day = dy*(xmin-x1);
+ if (dax >= day) continue;
+
+ clipyou = 0;
+ if ((wal->nextsector < 0) || (wal->cstat&dawalclipmask)) clipyou = 1;
+ else if (editstatus == 0)
+ {
+ if (rintersect(*x,*y,0,gx,gy,0,x1,y1,x2,y2,&dax,&day,&daz) == 0)
+ dax = *x, day = *y;
+ daz = getflorzofslope((short)dasect,dax,day);
+ daz2 = getflorzofslope(wal->nextsector,dax,day);
+
+ sec2 = &sector[wal->nextsector];
+ if (daz2 < daz-(1<<8))
+ if ((sec2->floorstat&1) == 0)
+ if ((*z) >= daz2-(flordist-1)) clipyou = 1;
+ if (clipyou == 0)
+ {
+ daz = getceilzofslope((short)dasect,dax,day);
+ daz2 = getceilzofslope(wal->nextsector,dax,day);
+ if (daz2 > daz+(1<<8))
+ if ((sec2->ceilingstat&1) == 0)
+ if ((*z) <= daz2+(ceildist-1)) clipyou = 1;
+ }
+ }
+
+ if (clipyou)
+ {
+ /* Add 2 boxes at endpoints */
+ bsz = walldist;
+ if (gx < 0) bsz = -bsz;
+ addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,(short)j+32768);
+ addclipline(x2-bsz,y2-bsz,x2-bsz,y2+bsz,(short)j+32768);
+ bsz = walldist;
+ if (gy < 0) bsz = -bsz;
+ addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,(short)j+32768);
+ addclipline(x2+bsz,y2-bsz,x2-bsz,y2-bsz,(short)j+32768);
+
+ dax = walldist;
+ if (dy > 0) dax = -dax;
+ day = walldist;
+ if (dx < 0) day = -day;
+ addclipline(x1+dax,y1+day,x2+dax,y2+day,(short)j+32768);
+ }
+ else
+ {
+ for(i=clipsectnum-1; i>=0; i--)
+ if (wal->nextsector == clipsectorlist[i]) break;
+ if (i < 0) clipsectorlist[clipsectnum++] = wal->nextsector;
+ }
+ }
+
+ for(j=headspritesect[dasect]; j>=0; j=nextspritesect[j])
+ {
+ spr = &sprite[j];
+ cstat = spr->cstat;
+ if ((cstat&dasprclipmask) == 0) continue;
+ x1 = spr->x;
+ y1 = spr->y;
+ switch(cstat&48)
+ {
+ case 0:
+ if ((x1 >= xmin) && (x1 <= xmax) && (y1 >= ymin) && (y1 <= ymax))
+ {
+ k = ((tiles[spr->picnum].dim.height*spr->yrepeat)<<2);
+ if (cstat&128) daz = spr->z+(k>>1);
+ else daz = spr->z;
+
+ if (tiles[spr->picnum].animFlags&0x00ff0000)
+ daz -= ((int32_t)((int8_t )((tiles[spr->picnum].animFlags>>16)&255))*spr->yrepeat<<2);
+
+ if (((*z) < daz+ceildist) && ((*z) > daz-k-flordist)){
+ bsz = (spr->clipdist<<2)+walldist;
+ if (gx < 0) bsz = -bsz;
+ addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,(short)j+49152);
+ bsz = (spr->clipdist<<2)+walldist;
+ if (gy < 0) bsz = -bsz;
+ addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,(short)j+49152);
+ }
+ }
+ break;
+ case 16:
+ k = ((tiles[spr->picnum].dim.height*spr->yrepeat)<<2);
+
+ if (cstat&128)
+ daz = spr->z+(k>>1);
+ else
+ daz = spr->z;
+
+ if (tiles[spr->picnum].animFlags&0x00ff0000)
+ daz -= ((int32_t)((int8_t )((tiles[spr->picnum].animFlags>>16)&255))*spr->yrepeat<<2);
+ daz2 = daz-k;
+ daz += ceildist;
+ daz2 -= flordist;
+ if (((*z) < daz) && ((*z) > daz2))
+ {
+ /*
+ * These lines get the 2 points of the rotated sprite
+ * Given: (x1, y1) starts out as the center point
+ */
+ tilenum = spr->picnum;
+ xoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>8)&255))+((int32_t)spr->xoffset);
+ if ((cstat&4) > 0) xoff = -xoff;
+ k = spr->ang;
+ l = spr->xrepeat;
+ dax = sintable[k&2047]*l;
+ day = sintable[(k+1536)&2047]*l;
+ l = tiles[tilenum].dim.width;
+ k = (l>>1)+xoff;
+ x1 -= mulscale16(dax,k);
+ x2 = x1+mulscale16(dax,l);
+ y1 -= mulscale16(day,k);
+ y2 = y1+mulscale16(day,l);
+ if (clipinsideboxline(cx,cy,x1,y1,x2,y2,rad) != 0)
+ {
+ dax = mulscale14(sintable[(spr->ang+256+512)&2047],walldist);
+ day = mulscale14(sintable[(spr->ang+256)&2047],walldist);
+
+ if ((x1-(*x))*(y2-(*y)) >= (x2-(*x))*(y1-(*y))) /* Front */
+ {
+ addclipline(x1+dax,y1+day,x2+day,y2-dax,(short)j+49152);
+ }
+ else
+ {
+ if ((cstat&64) != 0) continue;
+ addclipline(x2-dax,y2-day,x1-day,y1+dax,(short)j+49152);
+ }
+
+ /* Side blocker */
+ if ((x2-x1)*((*x)-x1) + (y2-y1)*((*y)-y1) < 0)
+ {
+ addclipline(x1-day,y1+dax,x1+dax,y1+day,(short)j+49152);
+ }
+ else if ((x1-x2)*((*x)-x2) + (y1-y2)*((*y)-y2) < 0)
+ {
+ addclipline(x2+day,y2-dax,x2-dax,y2-day,(short)j+49152);
+ }
+ }
+ }
+ break;
+ case 32:
+ daz = spr->z+ceildist;
+ daz2 = spr->z-flordist;
+ if (((*z) < daz) && ((*z) > daz2))
+ {
+ if ((cstat&64) != 0)
+ if (((*z) > spr->z) == ((cstat&8)==0)) continue;
+
+ tilenum = spr->picnum;
+ xoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>8)&255))+((int32_t)spr->xoffset);
+ yoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>16)&255))+((int32_t)spr->yoffset);
+ if ((cstat&4) > 0) xoff = -xoff;
+ if ((cstat&8) > 0) yoff = -yoff;
+
+ k = spr->ang;
+ cosang = sintable[(k+512)&2047];
+ sinang = sintable[k];
+ xspan = tiles[tilenum].dim.width;
+ xrepeat = spr->xrepeat;
+ yspan = tiles[tilenum].dim.height;
+ yrepeat = spr->yrepeat;
+
+ dax = ((xspan>>1)+xoff)*xrepeat;
+ day = ((yspan>>1)+yoff)*yrepeat;
+ rxi[0] = x1 + dmulscale16(sinang,dax,cosang,day);
+ ryi[0] = y1 + dmulscale16(sinang,day,-cosang,dax);
+ l = xspan*xrepeat;
+ rxi[1] = rxi[0] - mulscale16(sinang,l);
+ ryi[1] = ryi[0] + mulscale16(cosang,l);
+ l = yspan*yrepeat;
+ k = -mulscale16(cosang,l);
+ rxi[2] = rxi[1]+k;
+ rxi[3] = rxi[0]+k;
+ k = -mulscale16(sinang,l);
+ ryi[2] = ryi[1]+k;
+ ryi[3] = ryi[0]+k;
+
+ dax = mulscale14(sintable[(spr->ang-256+512)&2047],walldist);
+ day = mulscale14(sintable[(spr->ang-256)&2047],walldist);
+
+ if ((rxi[0]-(*x))*(ryi[1]-(*y)) < (rxi[1]-(*x))*(ryi[0]-(*y)))
+ {
+ if (clipinsideboxline(cx,cy,rxi[1],ryi[1],rxi[0],ryi[0],rad) != 0)
+ addclipline(rxi[1]-day,ryi[1]+dax,rxi[0]+dax,ryi[0]+day,(short)j+49152);
+ }
+ else if ((rxi[2]-(*x))*(ryi[3]-(*y)) < (rxi[3]-(*x))*(ryi[2]-(*y)))
+ {
+ if (clipinsideboxline(cx,cy,rxi[3],ryi[3],rxi[2],ryi[2],rad) != 0)
+ addclipline(rxi[3]+day,ryi[3]-dax,rxi[2]-dax,ryi[2]-day,(short)j+49152);
+ }
+
+ if ((rxi[1]-(*x))*(ryi[2]-(*y)) < (rxi[2]-(*x))*(ryi[1]-(*y)))
+ {
+ if (clipinsideboxline(cx,cy,rxi[2],ryi[2],rxi[1],ryi[1],rad) != 0)
+ addclipline(rxi[2]-dax,ryi[2]-day,rxi[1]-day,ryi[1]+dax,(short)j+49152);
+ }
+ else if ((rxi[3]-(*x))*(ryi[0]-(*y)) < (rxi[0]-(*x))*(ryi[3]-(*y)))
+ {
+ if (clipinsideboxline(cx,cy,rxi[0],ryi[0],rxi[3],ryi[3],rad) != 0)
+ addclipline(rxi[0]+dax,ryi[0]+day,rxi[3]+day,ryi[3]-dax,(short)j+49152);
+ }
+ }
+ break;
+ }
+ }
+ } while (clipsectcnt < clipsectnum);
+
+
+ hitwall = 0;
+ cnt = clipmoveboxtracenum;
+ do
+ {
+ intx = goalx;
+ inty = goaly;
+ if ((hitwall = raytrace(*x, *y, &intx, &inty)) >= 0)
+ {
+ lx = clipit[hitwall].x2-clipit[hitwall].x1;
+ ly = clipit[hitwall].y2-clipit[hitwall].y1;
+ templong2 = lx*lx + ly*ly;
+ if (templong2 > 0)
+ {
+ templong1 = (goalx-intx)*lx + (goaly-inty)*ly;
+
+ if ((klabs(templong1)>>11) < templong2)
+ i = divscale20(templong1,templong2);
+ else
+ i = 0;
+ goalx = mulscale20(lx,i)+intx;
+ goaly = mulscale20(ly,i)+inty;
+ }
+
+ templong1 = dmulscale6(lx,oxvect,ly,oyvect);
+ for(i=cnt+1; i<=clipmoveboxtracenum; i++)
+ {
+ j = hitwalls[i];
+ templong2 = dmulscale6(clipit[j].x2-clipit[j].x1,oxvect,clipit[j].y2-clipit[j].y1,oyvect);
+ if ((templong1^templong2) < 0)
+ {
+ updatesector(*x,*y,sectnum);
+ return(retval);
+ }
+ }
+
+ keepaway(&goalx, &goaly, hitwall);
+ xvect = ((goalx-intx)<<14);
+ yvect = ((goaly-inty)<<14);
+
+ if (cnt == clipmoveboxtracenum) retval = clipobjectval[hitwall];
+ hitwalls[cnt] = hitwall;
+ }
+ cnt--;
+
+ *x = intx;
+ *y = inty;
+ } while (((xvect|yvect) != 0) && (hitwall >= 0) && (cnt > 0));
+
+ for(j=0; j<clipsectnum; j++)
+ if (inside(*x,*y,clipsectorlist[j]) == 1)
+ {
+ *sectnum = clipsectorlist[j];
+ return(retval);
+ }
+
+ *sectnum = -1;
+ templong1 = 0x7fffffff;
+ for(j=numsectors-1; j>=0; j--)
+ if (inside(*x,*y,j) == 1)
+ {
+ if (sector[j].ceilingstat&2)
+ templong2 = (getceilzofslope((short)j,*x,*y)-(*z));
+ else
+ templong2 = (sector[j].ceilingz-(*z));
+
+ if (templong2 > 0)
+ {
+ if (templong2 < templong1)
+ {
+ *sectnum = j;
+ templong1 = templong2;
+ }
+ }
+ else
+ {
+ if (sector[j].floorstat&2)
+ templong2 = ((*z)-getflorzofslope((short)j,*x,*y));
+ else
+ templong2 = ((*z)-sector[j].floorz);
+
+ if (templong2 <= 0)
+ {
+ *sectnum = j;
+ return(retval);
+ }
+ if (templong2 < templong1)
+ {
+ *sectnum = j;
+ templong1 = templong2;
+ }
+ }
+ }
+
+ return(retval);
+}
+
+
+int pushmove(int32_t *x, int32_t *y, int32_t *z, short *sectnum,
+ int32_t walldist, int32_t ceildist, int32_t flordist,
+ uint32_t cliptype)
+{
+ sectortype *sec, *sec2;
+ walltype *wal;
+ int32_t i, j, k, t, dx, dy, dax, day, daz, daz2, bad, dir;
+// int32_t dasprclipmask;
+ int32_t dawalclipmask;
+ short startwall, endwall, clipsectcnt;
+ uint8_t bad2;
+
+ if ((*sectnum) < 0) return(-1);
+
+ dawalclipmask = (cliptype&65535);
+// dasprclipmask = (cliptype>>16);
+
+ k = 32;
+ dir = 1;
+ do
+ {
+ bad = 0;
+
+ clipsectorlist[0] = *sectnum;
+ clipsectcnt = 0;
+ clipsectnum = 1;
+ do
+ {
+ sec = &sector[clipsectorlist[clipsectcnt]];
+ if (dir > 0)
+ startwall = sec->wallptr, endwall = startwall + sec->wallnum;
+ else
+ endwall = sec->wallptr, startwall = endwall + sec->wallnum;
+
+ for(i=startwall,wal=&wall[startwall]; i!=endwall; i+=dir,wal+=dir)
+ if (clipinsidebox(*x,*y,i,walldist-4) == 1)
+ {
+ j = 0;
+ if (wal->nextsector < 0) j = 1;
+ if (wal->cstat&dawalclipmask) j = 1;
+ if (j == 0)
+ {
+ sec2 = &sector[wal->nextsector];
+
+
+ /* Find closest point on wall (dax, day) to (*x, *y) */
+ dax = wall[wal->point2].x-wal->x;
+ day = wall[wal->point2].y-wal->y;
+ daz = dax*((*x)-wal->x) + day*((*y)-wal->y);
+ if (daz <= 0)
+ t = 0;
+ else
+ {
+ daz2 = dax*dax+day*day;
+ if (daz >= daz2) t = (1<<30);
+ else t = divscale30(daz,daz2);
+ }
+ dax = wal->x + mulscale30(dax,t);
+ day = wal->y + mulscale30(day,t);
+
+
+ daz = getflorzofslope(clipsectorlist[clipsectcnt],dax,day);
+ daz2 = getflorzofslope(wal->nextsector,dax,day);
+ if ((daz2 < daz-(1<<8)) && ((sec2->floorstat&1) == 0))
+ if (*z >= daz2-(flordist-1)) j = 1;
+
+ daz = getceilzofslope(clipsectorlist[clipsectcnt],dax,day);
+ daz2 = getceilzofslope(wal->nextsector,dax,day);
+ if ((daz2 > daz+(1<<8)) && ((sec2->ceilingstat&1) == 0))
+ if (*z <= daz2+(ceildist-1)) j = 1;
+ }
+ if (j != 0)
+ {
+ j = getangle(wall[wal->point2].x-wal->x,wall[wal->point2].y-wal->y);
+ dx = (sintable[(j+1024)&2047]>>11);
+ dy = (sintable[(j+512)&2047]>>11);
+ bad2 = 16;
+ do
+ {
+ *x = (*x) + dx;
+ *y = (*y) + dy;
+ bad2--;
+ if (bad2 == 0) break;
+ } while (clipinsidebox(*x,*y,i,walldist-4) != 0);
+ bad = -1;
+ k--;
+ if (k <= 0) return(bad);
+ updatesector(*x,*y,sectnum);
+ }
+ else
+ {
+ for(j=clipsectnum-1; j>=0; j--)
+ if (wal->nextsector == clipsectorlist[j]) break;
+ if (j < 0) clipsectorlist[clipsectnum++] = wal->nextsector;
+ }
+ }
+
+ clipsectcnt++;
+ } while (clipsectcnt < clipsectnum);
+ dir = -dir;
+ } while (bad != 0);
+
+ return(bad);
+}
+
+/*
+ FCS: x and y are the new position of the entity that has just moved:
+ lastKnownSector is an hint (the last known sectorID of the entity).
+
+ Thanks to the "hint", the algorithm check:
+ 1. Is (x,y) inside sectors[sectnum].
+ 2. Flood in sectnum portal and check again if (x,y) is inside.
+ 3. Do a linear search on sectors[sectnum] from 0 to numSectors.
+
+ Note: Inside uses cross_product and return as soon as the point switch
+ from one side to the other.
+ */
+void updatesector(int32_t x, int32_t y, short *lastKnownSector)
+{
+ walltype *wal;
+ int32_t i, j;
+
+ //First check the last sector where (old_x,old_y) was before being updated to (x,y)
+ if (inside(x,y,*lastKnownSector) == 1)
+ {
+ //We found it and (x,y) is still in the same sector: nothing to update !
+ return;
+ }
+
+ // Seems (x,y) moved into an other sector....hopefully one connected via a portal. Let's flood in each portal.
+ if ((*lastKnownSector >= 0) && (*lastKnownSector < numsectors))
+ {
+ wal = &wall[sector[*lastKnownSector].wallptr];
+ j = sector[*lastKnownSector].wallnum;
+ do
+ {
+ i = wal->nextsector;
+ if (i >= 0)
+ if (inside(x,y,(short)i) == 1)
+ {
+ *lastKnownSector = i;
+ return;
+ }
+ wal++;
+ j--;
+ } while (j != 0);
+ }
+
+ //Damn that is a BIG move, still cannot find which sector (x,y) belongs to. Let's search via linear search.
+ for(i=numsectors-1; i>=0; i--)
+ {
+ if (inside(x,y,(short)i) == 1)
+ {
+ *lastKnownSector = i;
+ return;
+ }
+ }
+ // (x,y) is contained in NO sector. (x,y) is likely out of the map.
+ *lastKnownSector = -1;
+}
+
+
+void rotatepoint(int32_t xpivot, int32_t ypivot, int32_t x, int32_t y, short daang, int32_t *x2, int32_t *y2)
+{
+ int32_t dacos, dasin;
+
+ dacos = sintable[(daang+2560)&2047];
+ dasin = sintable[(daang+2048)&2047];
+ x -= xpivot;
+ y -= ypivot;
+ *x2 = dmulscale14(x,dacos,-y,dasin) + xpivot;
+ *y2 = dmulscale14(y,dacos,x,dasin) + ypivot;
+}
+
+
+int initmouse(void)
+{
+ return(moustat = setupmouse());
+}
+
+
+void getmousevalues(short *mousx, short *mousy, short *bstatus)
+{
+ if (moustat == 0) {
+ *mousx = 0;
+ *mousy = 0;
+ *bstatus = 0;
+ return;
+ }
+ readmousexy(mousx,mousy);
+ readmousebstatus(bstatus);
+}
+
+void draw2dgrid(int32_t posxe, int32_t posye, short ange, int32_t zoome, short gride)
+{
+ int32_t i, xp1, yp1, xp2=0, yp2, tempy; // tempint;
+ uint8_t mask;
+
+ if (gride > 0)
+ {
+ yp1 = 200-mulscale14(posye+131072,zoome);
+ if (yp1 < 0) yp1 = 0;
+ yp2 = 200-mulscale14(posye-131072,zoome);
+ if (yp2 >= ydim16) yp2 = ydim16-1;
+
+ if ((yp1 < ydim16) && (yp2 >= 0) && (yp2 >= yp1))
+ {
+ setcolor16(8);
+
+// tempint = ((yp1*640+pageoffset)>>3)+(int32_t)_getVideoBase();
+ tempy = yp2-yp1+1;
+ mask = 0;
+ xp1 = 320-mulscale14(posxe+131072,zoome);
+
+ for(i=-131072; i<=131072; i+=(2048>>gride))
+ {
+ xp2 = xp1;
+ xp1 = 320-mulscale14(posxe-i,zoome);
+
+ if (xp1 >= 640) break;
+ if (xp1 >= 0)
+ {
+
+
+ drawline16(xp1, 0, xp1, tempy, 8);
+ }
+ }
+ if ((i >= 131072) && (xp1 < 640))
+ xp2 = xp1;
+ if ((mask != 0) && ((xp2>>3) >= 0) && ((xp2>>3) < 80))
+ {
+ /* !!! Does this code ever get hit? Do something with this! */
+ fprintf (stderr, "STUB: %s:%d\n",__FILE__,__LINE__);
+ }
+ }
+
+ xp1 = mulscale14(posxe+131072,zoome);
+ xp2 = mulscale14(posxe-131072,zoome);
+ tempy = 0x80000000;
+ for(i=-131072; i<=131072; i+=(2048>>gride))
+ {
+ yp1 = (((posye-i)*zoome)>>14);
+ if (yp1 != tempy)
+ {
+ if ((yp1 > 200-ydim16) && (yp1 <= 200))
+ {
+ drawline16(320-xp1,200-yp1,320-xp2,200-yp1,8);
+ tempy = yp1;
+ }
+ }
+ }
+ }
+}
+
+void draw2dscreen(int32_t posxe, int32_t posye, short ange, int32_t zoome, short gride)
+{
+ walltype *wal;
+ int32_t i, j, xp1, yp1, xp2, yp2, tempint;
+ uint8_t col;
+
+ if (qsetmode == 200) return;
+
+ if (editstatus == 0)
+ {
+ faketimerhandler();
+ clear2dscreen();
+
+ faketimerhandler();
+ draw2dgrid(posxe,posye,ange,zoome,gride);
+ }
+
+ faketimerhandler();
+ for(i=numwalls-1,wal=&wall[i]; i>=0; i--,wal--)
+ {
+ if (editstatus == 0)
+ {
+ if ((show2dwall[i>>3]&pow2char[i&7]) == 0) continue;
+ j = wal->nextwall;
+ if ((j >= 0) && (i > j))
+ if ((show2dwall[j>>3]&pow2char[j&7]) > 0) continue;
+ }
+ else
+ {
+ j = wal->nextwall;
+ if ((j >= 0) && (i > j)) continue;
+ }
+
+ if (j < 0)
+ {
+ col = 7;
+ if (i == linehighlight) col += ((numframes&2)<<2);
+ }
+ else
+ {
+ col = 4;
+ if ((wal->cstat&1) != 0) col = 5;
+ if ((i == linehighlight) || ((linehighlight >= 0) && (i == wall[linehighlight].nextwall)))
+ col += ((numframes&2)<<2);
+ }
+
+ xp1 = mulscale14(wal->x-posxe,zoome);
+ yp1 = mulscale14(wal->y-posye,zoome);
+ xp2 = mulscale14(wall[wal->point2].x-posxe,zoome);
+ yp2 = mulscale14(wall[wal->point2].y-posye,zoome);
+
+ if ((wal->cstat&64) > 0)
+ {
+ if (klabs(xp2-xp1) >= klabs(yp2-yp1))
+ {
+ drawline16(320+xp1,200+yp1+1,320+xp2,200+yp2+1,col);
+ drawline16(320+xp1,200+yp1-1,320+xp2,200+yp2-1,col);
+ }
+ else
+ {
+ drawline16(320+xp1+1,200+yp1,320+xp2+1,200+yp2,col);
+ drawline16(320+xp1-1,200+yp1,320+xp2-1,200+yp2,col);
+ }
+ col += 8;
+ }
+ drawline16(320+xp1,200+yp1,320+xp2,200+yp2,col);
+
+ if ((zoome >= 256) && (editstatus == 1))
+ if (((320+xp1) >= 2) && ((320+xp1) <= 637))
+ if (((200+yp1) >= 2) && ((200+yp1) <= ydim16-3))
+ {
+ col = 2;
+ if (i == pointhighlight) col += ((numframes&2)<<2);
+ else if ((highlightcnt > 0) && (editstatus == 1))
+ {
+ if (show2dwall[i>>3]&pow2char[i&7])
+ col += ((numframes&2)<<2);
+ }
+
+
+ tempint = (mul5(200+yp1)<<7)+(320+xp1);
+
+ setcolor16(col);
+
+ drawpixel16(tempint-2-1280);
+ drawpixel16(tempint-1-1280);
+ drawpixel16(tempint+0-1280);
+ drawpixel16(tempint+1-1280);
+ drawpixel16(tempint+2-1280);
+
+ drawpixel16(tempint-2+1280);
+ drawpixel16(tempint-1+1280);
+ drawpixel16(tempint+0+1280);
+ drawpixel16(tempint+1+1280);
+ drawpixel16(tempint+2+1280);
+
+ drawpixel16(tempint-2-640);
+ drawpixel16(tempint-2+0);
+ drawpixel16(tempint-2+640);
+
+ drawpixel16(tempint+2-640);
+ drawpixel16(tempint+2+0);
+ drawpixel16(tempint+2+640);
+ }
+ }
+ faketimerhandler();
+
+ if ((zoome >= 256) || (editstatus == 0))
+ for(i=0; i<numsectors; i++)
+ for(j=headspritesect[i]; j>=0; j=nextspritesect[j])
+ if ((editstatus == 1) || (show2dsprite[j>>3]&pow2char[j&7]))
+ {
+ col = 3;
+ if ((sprite[j].cstat&1) > 0) col = 5;
+ if (editstatus == 1)
+ {
+ if (j+16384 == pointhighlight)
+ col += ((numframes&2)<<2);
+ else if ((highlightcnt > 0) && (editstatus == 1))
+ {
+ if (show2dsprite[j>>3]&pow2char[j&7])
+ col += ((numframes&2)<<2);
+ }
+ }
+
+ xp1 = mulscale14(sprite[j].x-posxe,zoome);
+ yp1 = mulscale14(sprite[j].y-posye,zoome);
+ if (((320+xp1) >= 2) && ((320+xp1) <= 637))
+ if (((200+yp1) >= 2) && ((200+yp1) <= ydim16-3))
+ {
+
+ tempint = (mul5(200+yp1)<<7)+(320+xp1);
+
+
+ setcolor16(col);
+ drawpixel16(tempint-1-1280);
+ drawpixel16(tempint+0-1280);
+ drawpixel16(tempint+1-1280);
+
+ drawpixel16(tempint-1+1280);
+ drawpixel16(tempint+0+1280);
+ drawpixel16(tempint+1+1280);
+
+ drawpixel16(tempint-2-640);
+ drawpixel16(tempint-2+0);
+ drawpixel16(tempint-2+640);
+
+ drawpixel16(tempint+2-640);
+ drawpixel16(tempint+2+0);
+ drawpixel16(tempint+2+640);
+
+ drawpixel16(tempint+1+640);
+ drawpixel16(tempint-1+640);
+ drawpixel16(tempint+1-640);
+ drawpixel16(tempint-1-640);
+
+ xp2 = mulscale11(sintable[(sprite[j].ang+2560)&2047],zoome) / 768;
+ yp2 = mulscale11(sintable[(sprite[j].ang+2048)&2047],zoome) / 768;
+
+ if ((sprite[j].cstat&256) > 0)
+ {
+ if (((sprite[j].ang+256)&512) == 0)
+ {
+ drawline16(320+xp1,200+yp1-1,320+xp1+xp2,200+yp1+yp2-1,col);
+ drawline16(320+xp1,200+yp1+1,320+xp1+xp2,200+yp1+yp2+1,col);
+ }
+ else
+ {
+ drawline16(320+xp1-1,200+yp1,320+xp1+xp2-1,200+yp1+yp2,col);
+ drawline16(320+xp1+1,200+yp1,320+xp1+xp2+1,200+yp1+yp2,col);
+ }
+ col += 8;
+ }
+ drawline16(320+xp1,200+yp1,320+xp1+xp2,200+yp1+yp2,col);
+ }
+ }
+
+ faketimerhandler();
+ xp1 = mulscale11(sintable[(ange+2560)&2047],zoome) / 768; /* Draw white arrow */
+ yp1 = mulscale11(sintable[(ange+2048)&2047],zoome) / 768;
+ drawline16(320+xp1,200+yp1,320-xp1,200-yp1,15);
+ drawline16(320+xp1,200+yp1,320+yp1,200-xp1,15);
+ drawline16(320+xp1,200+yp1,320-yp1,200+xp1,15);
+}
+
+
+/*
+ * This is ryan's change. SDL requires me to call SDL_UpdateRect() to force
+ * vid updates without a SDL_Flip() call, but there's no such thing in the
+ * DOS version of this program, so text won't show up sometimes without
+ * my update call in Linux. However, to get a nice shadow effect on some
+ * text, Ken draws a string at an offset and darker, and then on top of it
+ * draws the actual string. Two SDL_UpdateRect() calls in over top of each
+ * other cause flicker, so I have this function here so the shadow can
+ * be drawn with _noupdate, and the actual string is draw with an update.
+ */
+void printext256(int32_t xpos, int32_t ypos, short col, short backcol, char* name, uint8_t fontsize)
+{
+ int32_t stx, i, x, y, charxsiz;
+ uint8_t *fontptr, *letptr, *ptr;
+
+
+
+ stx = xpos;
+
+ if (fontsize) {
+ fontptr = smalltextfont;
+ charxsiz = 4;
+ }
+ else {
+ fontptr = textfont;
+ charxsiz = 8;
+ }
+
+ //For each character in the string.
+ for(i=0; name[i]; i++)
+ {
+ letptr = &fontptr[name[i]<<3];
+ ptr = ylookup[ypos+7]+(stx-fontsize)+frameplace;
+ for(y=7; y>=0; y--)
+ {
+ for(x=charxsiz-1; x>=0; x--)
+ {
+ if (letptr[y]&pow2char[7-fontsize-x])
+ ptr[x] = (uint8_t )col;
+ else if (backcol >= 0)
+ ptr[x] = (uint8_t )backcol;
+ }
+ ptr -= ylookup[1];
+ }
+ stx += charxsiz;
+ }
+
+ _updateScreenRect(xpos, ypos, charxsiz * i, 8);
+}
+
+int krand()
+{
+ randomseed = (randomseed*27584621)+1;
+ return(((uint32_t )randomseed)>>16);
+}
+
+
+void getzrange(int32_t x, int32_t y, int32_t z, short sectnum,
+ int32_t *ceilz, int32_t *ceilhit, int32_t *florz, int32_t *florhit,
+ int32_t walldist, uint32_t cliptype)
+{
+ sectortype *sec;
+ walltype *wal, *wal2;
+ spritetype *spr;
+ int32_t clipsectcnt, startwall, endwall, tilenum, xoff, yoff, dax, day;
+ int32_t xmin, ymin, xmax, ymax, i, j, k, l, daz, daz2, dx, dy;
+ int32_t x1, y1, x2, y2, x3, y3, x4, y4, ang, cosang, sinang;
+ int32_t xspan, yspan, xrepeat, yrepeat, dasprclipmask, dawalclipmask;
+ short cstat;
+ uint8_t clipyou;
+
+ if (sectnum < 0)
+ {
+ *ceilz = 0x80000000;
+ *ceilhit = -1;
+ *florz = 0x7fffffff;
+ *florhit = -1;
+ return;
+ }
+
+ /* Extra walldist for sprites on sector lines */
+ i = walldist+MAXCLIPDIST+1;
+ xmin = x-i;
+ ymin = y-i;
+ xmax = x+i;
+ ymax = y+i;
+
+ getzsofslope(sectnum,x,y,ceilz,florz);
+ *ceilhit = sectnum+16384;
+ *florhit = sectnum+16384;
+
+ dawalclipmask = (cliptype&65535);
+ dasprclipmask = (cliptype>>16);
+
+ clipsectorlist[0] = sectnum;
+ clipsectcnt = 0;
+ clipsectnum = 1;
+
+ do /* Collect sectors inside your square first */
+ {
+ sec = &sector[clipsectorlist[clipsectcnt]];
+ startwall = sec->wallptr;
+ endwall = startwall + sec->wallnum;
+ for(j=startwall,wal=&wall[startwall]; j<endwall; j++,wal++)
+ {
+ k = wal->nextsector;
+ if (k >= 0)
+ {
+ wal2 = &wall[wal->point2];
+ x1 = wal->x;
+ x2 = wal2->x;
+ if ((x1 < xmin) && (x2 < xmin)) continue;
+ if ((x1 > xmax) && (x2 > xmax)) continue;
+ y1 = wal->y;
+ y2 = wal2->y;
+ if ((y1 < ymin) && (y2 < ymin)) continue;
+ if ((y1 > ymax) && (y2 > ymax)) continue;
+
+ dx = x2-x1;
+ dy = y2-y1;
+ if (dx*(y-y1) < (x-x1)*dy) continue; /* back */
+ if (dx > 0) dax = dx*(ymin-y1);
+ else dax = dx*(ymax-y1);
+ if (dy > 0) day = dy*(xmax-x1);
+ else day = dy*(xmin-x1);
+ if (dax >= day) continue;
+
+ if (wal->cstat&dawalclipmask) continue;
+ sec = &sector[k];
+ if (editstatus == 0)
+ {
+ if (((sec->ceilingstat&1) == 0) && (z <= sec->ceilingz+(3<<8))) continue;
+ if (((sec->floorstat&1) == 0) && (z >= sec->floorz-(3<<8))) continue;
+ }
+
+ for(i=clipsectnum-1; i>=0; i--) if (clipsectorlist[i] == k) break;
+ if (i < 0) clipsectorlist[clipsectnum++] = k;
+
+ if ((x1 < xmin+MAXCLIPDIST) && (x2 < xmin+MAXCLIPDIST)) continue;
+ if ((x1 > xmax-MAXCLIPDIST) && (x2 > xmax-MAXCLIPDIST)) continue;
+ if ((y1 < ymin+MAXCLIPDIST) && (y2 < ymin+MAXCLIPDIST)) continue;
+ if ((y1 > ymax-MAXCLIPDIST) && (y2 > ymax-MAXCLIPDIST)) continue;
+ if (dx > 0) dax += dx*MAXCLIPDIST;
+ else dax -= dx*MAXCLIPDIST;
+ if (dy > 0) day -= dy*MAXCLIPDIST;
+ else day += dy*MAXCLIPDIST;
+ if (dax >= day) continue;
+
+ /* It actually got here, through all the continue's! */
+ getzsofslope((short)k,x,y,&daz,&daz2);
+ if (daz > *ceilz) {
+ *ceilz = daz;
+ *ceilhit = k+16384;
+ }
+ if (daz2 < *florz) {
+ *florz = daz2;
+ *florhit = k+16384;
+ }
+ }
+ }
+ clipsectcnt++;
+ } while (clipsectcnt < clipsectnum);
+
+ for(i=0; i<clipsectnum; i++)
+ {
+ for(j=headspritesect[clipsectorlist[i]]; j>=0; j=nextspritesect[j])
+ {
+ spr = &sprite[j];
+ cstat = spr->cstat;
+ if (cstat&dasprclipmask)
+ {
+ x1 = spr->x;
+ y1 = spr->y;
+
+ clipyou = 0;
+ switch(cstat&48)
+ {
+ case 0:
+ k = walldist+(spr->clipdist<<2)+1;
+ if ((klabs(x1-x) <= k) && (klabs(y1-y) <= k))
+ {
+ daz = spr->z;
+ k = ((tiles[spr->picnum].dim.height*spr->yrepeat)<<1);
+ if (cstat&128)
+ daz += k;
+ if (tiles[spr->picnum].animFlags&0x00ff0000) daz -= ((int32_t)((int8_t )((tiles[spr->picnum].animFlags>>16)&255))*spr->yrepeat<<2);
+ daz2 = daz - (k<<1);
+ clipyou = 1;
+ }
+ break;
+ case 16:
+ tilenum = spr->picnum;
+ xoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>8)&255))+((int32_t)spr->xoffset);
+ if ((cstat&4) > 0) xoff = -xoff;
+ k = spr->ang;
+ l = spr->xrepeat;
+ dax = sintable[k&2047]*l;
+ day = sintable[(k+1536)&2047]*l;
+ l = tiles[tilenum].dim.width;
+ k = (l>>1)+xoff;
+ x1 -= mulscale16(dax,k);
+ x2 = x1+mulscale16(dax,l);
+ y1 -= mulscale16(day,k);
+ y2 = y1+mulscale16(day,l);
+ if (clipinsideboxline(x,y,x1,y1,x2,y2,walldist+1) != 0)
+ {
+ daz = spr->z;
+ k = ((tiles[spr->picnum].dim.height*spr->yrepeat)<<1);
+ if (cstat&128)
+ daz += k;
+
+ if (tiles[spr->picnum].animFlags&0x00ff0000)
+ daz -= ((int32_t)((int8_t )((tiles[spr->picnum].animFlags>>16)&255))*spr->yrepeat<<2);
+
+ daz2 = daz-(k<<1);
+ clipyou = 1;
+ }
+ break;
+ case 32:
+ daz = spr->z;
+ daz2 = daz;
+
+ if ((cstat&64) != 0)
+ if ((z > daz) == ((cstat&8)==0)) continue;
+
+ tilenum = spr->picnum;
+ xoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>8)&255))+((int32_t)spr->xoffset);
+ yoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>16)&255))+((int32_t)spr->yoffset);
+ if ((cstat&4) > 0) xoff = -xoff;
+ if ((cstat&8) > 0) yoff = -yoff;
+
+ ang = spr->ang;
+ cosang = sintable[(ang+512)&2047];
+ sinang = sintable[ang];
+ xspan = tiles[tilenum].dim.width;
+ xrepeat = spr->xrepeat;
+ yspan = tiles[tilenum].dim.height;
+ yrepeat = spr->yrepeat;
+
+ dax = ((xspan>>1)+xoff)*xrepeat;
+ day = ((yspan>>1)+yoff)*yrepeat;
+ x1 += dmulscale16(sinang,dax,cosang,day)-x;
+ y1 += dmulscale16(sinang,day,-cosang,dax)-y;
+ l = xspan*xrepeat;
+ x2 = x1 - mulscale16(sinang,l);
+ y2 = y1 + mulscale16(cosang,l);
+ l = yspan*yrepeat;
+ k = -mulscale16(cosang,l);
+ x3 = x2+k;
+ x4 = x1+k;
+ k = -mulscale16(sinang,l);
+ y3 = y2+k;
+ y4 = y1+k;
+
+ dax = mulscale14(sintable[(spr->ang-256+512)&2047],walldist+4);
+ day = mulscale14(sintable[(spr->ang-256)&2047],walldist+4);
+ x1 += dax;
+ x2 -= day;
+ x3 -= dax;
+ x4 += day;
+ y1 += day;
+ y2 += dax;
+ y3 -= day;
+ y4 -= dax;
+
+ if ((y1^y2) < 0)
+ {
+ if ((x1^x2) < 0) clipyou ^= (x1*y2<x2*y1)^(y1<y2);
+ else if (x1 >= 0) clipyou ^= 1;
+ }
+ if ((y2^y3) < 0)
+ {
+ if ((x2^x3) < 0) clipyou ^= (x2*y3<x3*y2)^(y2<y3);
+ else if (x2 >= 0) clipyou ^= 1;
+ }
+ if ((y3^y4) < 0)
+ {
+ if ((x3^x4) < 0) clipyou ^= (x3*y4<x4*y3)^(y3<y4);
+ else if (x3 >= 0) clipyou ^= 1;
+ }
+ if ((y4^y1) < 0)
+ {
+ if ((x4^x1) < 0) clipyou ^= (x4*y1<x1*y4)^(y4<y1);
+ else if (x4 >= 0) clipyou ^= 1;
+ }
+ break;
+ }
+
+ if (clipyou != 0)
+ {
+ if ((z > daz) && (daz > *ceilz)) {
+ *ceilz = daz;
+ *ceilhit = j+49152;
+ }
+ if ((z < daz2) && (daz2 < *florz)) {
+ *florz = daz2;
+ *florhit = j+49152;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void setview(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
+{
+ int32_t i;
+
+ windowx1 = x1;
+ wx1 = (x1<<12);
+ windowy1 = y1;
+ wy1 = (y1<<12);
+ windowx2 = x2;
+ wx2 = ((x2+1)<<12);
+ windowy2 = y2;
+ wy2 = ((y2+1)<<12);
+
+ xdimen = (x2-x1)+1;
+ halfxdimen = (xdimen>>1);
+ xdimenrecip = divscale32(1L,xdimen);
+ ydimen = (y2-y1)+1;
+
+ setaspect(65536L,(int32_t)divscale16(ydim*320L,xdim*200L));
+
+ for(i=0; i<windowx1; i++) {
+ startumost[i] = 1, startdmost[i] = 0;
+ }
+ for(i=windowx1; i<=windowx2; i++)
+ {
+ startumost[i] = windowy1, startdmost[i] = windowy2+1;
+ }
+ for(i=windowx2+1; i<xdim; i++) {
+ startumost[i] = 1, startdmost[i] = 0;
+ }
+
+ viewoffset = windowy1*bytesperline + windowx1;
+
+ if (stereomode)
+ {
+ ostereopixelwidth = stereopixelwidth;
+ xdimen = (windowx2-windowx1+1)+(stereopixelwidth<<1);
+ halfxdimen = (xdimen>>1);
+ xdimenrecip = divscale32(1L,xdimen);
+ setaspect((int32_t)divscale16(xdimen,windowx2-windowx1+1),yxaspect);
+ }
+}
+
+
+void setaspect(int32_t daxrange, int32_t daaspect)
+{
+ viewingrange = daxrange;
+ viewingrangerecip = divscale32(1L,daxrange);
+
+ yxaspect = daaspect;
+ xyaspect = divscale32(1,yxaspect);
+ xdimenscale = scale(xdimen,yxaspect,320);
+ xdimscale = scale(320,xyaspect,xdimen);
+}
+
+
+void flushperms(void)
+{
+ permhead = permtail = 0;
+}
+
+// Render a sprite on screen. This is used by the Engine but also the Game module
+// when drawing the HUD or the Weapon held by the player !!!
+void rotatesprite(int32_t sx, int32_t sy, int32_t z, short a, short picnum,
+ int8_t dashade, uint8_t dapalnum, uint8_t dastat,
+ int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2)
+{
+ int32_t i;
+ permfifotype *per, *per2;
+
+ //If 2D target coordinate do not make sense (left > right)..
+ if ((cx1 > cx2) || (cy1 > cy2))
+ return;
+
+ if (z <= 16)
+ return;
+
+ if (tiles[picnum].animFlags&192)
+ picnum += animateoffs(picnum);
+
+ //Does the tile has negative dimensions ?
+ if ((tiles[picnum].dim.width <= 0) || (tiles[picnum].dim.height <= 0))
+ return;
+
+ if (((dastat&128) == 0) || (numpages < 2) || (beforedrawrooms != 0))
+ dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,cx1,cy1,cx2,cy2);
+
+ if ((dastat&64) && (cx1 <= 0) && (cy1 <= 0) && (cx2 >= xdim-1) && (cy2 >= ydim-1) &&
+ (sx == (160<<16)) && (sy == (100<<16)) && (z == 65536L) && (a == 0) && ((dastat&1) == 0))
+ permhead = permtail = 0;
+
+ if ((dastat&128) == 0) return;
+ if (numpages >= 2)
+ {
+ per = &permfifo[permhead];
+ per->sx = sx;
+ per->sy = sy;
+ per->z = z;
+ per->a = a;
+ per->picnum = picnum;
+ per->dashade = dashade;
+ per->dapalnum = dapalnum;
+ per->dastat = dastat;
+ per->pagesleft = numpages+((beforedrawrooms&1)<<7);
+ per->cx1 = cx1;
+ per->cy1 = cy1;
+ per->cx2 = cx2;
+ per->cy2 = cy2;
+
+ /* Would be better to optimize out true bounding boxes */
+ if (dastat&64) /* If non-masking write, checking for overlapping cases */
+ {
+ for(i=permtail; i!=permhead; i=((i+1)&(MAXPERMS-1)))
+ {
+ per2 = &permfifo[i];
+ if ((per2->pagesleft&127) == 0) continue;
+ if (per2->sx != per->sx) continue;
+ if (per2->sy != per->sy) continue;
+ if (per2->z != per->z) continue;
+ if (per2->a != per->a) continue;
+ if (tiles[per2->picnum].dim.width > tiles[per->picnum].dim.width)
+ continue;
+
+ if (tiles[per2->picnum].dim.height > tiles[per->picnum].dim.height)
+ continue;
+ if (per2->cx1 < per->cx1) continue;
+ if (per2->cy1 < per->cy1) continue;
+ if (per2->cx2 > per->cx2) continue;
+ if (per2->cy2 > per->cy2) continue;
+ per2->pagesleft = 0;
+ }
+ if ((per->z == 65536) && (per->a == 0))
+ for(i=permtail; i!=permhead; i=((i+1)&(MAXPERMS-1)))
+ {
+ per2 = &permfifo[i];
+ if ((per2->pagesleft&127) == 0) continue;
+ if (per2->z != 65536) continue;
+ if (per2->a != 0) continue;
+ if (per2->cx1 < per->cx1) continue;
+ if (per2->cy1 < per->cy1) continue;
+ if (per2->cx2 > per->cx2) continue;
+ if (per2->cy2 > per->cy2) continue;
+ if ((per2->sx>>16) < (per->sx>>16)) continue;
+ if ((per2->sy>>16) < (per->sy>>16)) continue;
+ if ((per2->sx>>16)+tiles[per2->picnum].dim.width > (per->sx>>16)+tiles[per->picnum].dim.width)
+ continue;
+ if ((per2->sy>>16)+tiles[per2->picnum].dim.height > (per->sy>>16)+tiles[per->picnum].dim.height)
+ continue;
+ per2->pagesleft = 0;
+ }
+ }
+
+ permhead = ((permhead+1)&(MAXPERMS-1));
+ }
+}
+
+
+static int getclosestcol(int32_t r, int32_t g, int32_t b)
+{
+ int32_t i, j, k, dist, mindist, retcol;
+ uint8_t *pal1;
+
+ j = (r>>3)*FASTPALGRIDSIZ*FASTPALGRIDSIZ+(g>>3)*FASTPALGRIDSIZ+(b>>3)+FASTPALGRIDSIZ*FASTPALGRIDSIZ+FASTPALGRIDSIZ+1;
+ mindist = min(rdist[coldist[r&7]+64+8],gdist[coldist[g&7]+64+8]);
+ mindist = min(mindist,bdist[coldist[b&7]+64+8]);
+ mindist++;
+
+ r = 64-r;
+ g = 64-g;
+ b = 64-b;
+
+ retcol = -1;
+ for(k=26; k>=0; k--)
+ {
+ i = colscan[k]+j;
+ if ((colhere[i>>3]&pow2char[i&7]) == 0) continue;
+ i = colhead[i];
+ do
+ {
+ pal1 = (uint8_t *)&palette[i*3];
+ dist = gdist[pal1[1]+g];
+ if (dist < mindist)
+ {
+ dist += rdist[pal1[0]+r];
+ if (dist < mindist)
+ {
+ dist += bdist[pal1[2]+b];
+ if (dist < mindist) {
+ mindist = dist;
+ retcol = i;
+ }
+ }
+ }
+ i = colnext[i];
+ } while (i >= 0);
+ }
+ if (retcol >= 0) return(retcol);
+
+ mindist = 0x7fffffff;
+ pal1 = (uint8_t *)&palette[768-3];
+ for(i=255; i>=0; i--,pal1-=3)
+ {
+ dist = gdist[pal1[1]+g];
+ if (dist >= mindist) continue;
+ dist += rdist[pal1[0]+r];
+ if (dist >= mindist) continue;
+ dist += bdist[pal1[2]+b];
+ if (dist >= mindist) continue;
+ mindist = dist;
+ retcol = i;
+ }
+ return(retcol);
+}
+
+
+void makepalookup(int32_t palnum, uint8_t *remapbuf, int8_t r,
+ int8_t g, int8_t b, uint8_t dastat)
+{
+ int32_t i, j, palscale;
+ uint8_t *ptr, *ptr2;
+
+ if (paletteloaded == 0)
+ return;
+
+ if (palookup[palnum] == NULL)
+ {
+ /* Allocate palookup buffer */
+ if ((palookup[palnum] = (uint8_t *)kkmalloc(numpalookups<<8)) == NULL)
+ allocache((int32_t *)&palookup[palnum],numpalookups<<8,&permanentlock);
+ }
+
+ if (dastat == 0) return;
+ if ((r|g|b|63) != 63) return;
+
+ if ((r|g|b) == 0)
+ {
+ for(i=0; i<256; i++)
+ {
+ ptr = (uint8_t *)(FP_OFF(palookup[0])+remapbuf[i]);
+ ptr2 = (uint8_t *)(FP_OFF(palookup[palnum])+i);
+ for(j=0; j<numpalookups; j++)
+ {
+ *ptr2 = *ptr;
+ ptr += 256;
+ ptr2 += 256;
+ }
+ }
+ }
+ else
+ {
+ ptr2 = (uint8_t *)FP_OFF(palookup[palnum]);
+ for(i=0; i<numpalookups; i++)
+ {
+ palscale = divscale16(i,numpalookups);
+ for(j=0; j<256; j++)
+ {
+ ptr = (uint8_t *)&palette[remapbuf[j]*3];
+ *ptr2++ = getclosestcol((int32_t)ptr[0]+mulscale16(r-ptr[0],palscale),
+ (int32_t)ptr[1]+mulscale16(g-ptr[1],palscale),
+ (int32_t)ptr[2]+mulscale16(b-ptr[2],palscale));
+ }
+ }
+ }
+}
+
+
+void setbrightness(uint8_t dabrightness, uint8_t *dapal)
+{
+ int32_t i, k;
+ uint8_t newPalette[256*4];
+
+ //Clamp bightness to [0-15]
+ curbrightness = min(max(dabrightness,0),15);
+
+ k = 0;
+
+ for(i=0; i<256; i++){
+ newPalette[k++] = britable[curbrightness][dapal[i*3+2]];
+ newPalette[k++] = britable[curbrightness][dapal[i*3+1]];
+ newPalette[k++] = britable[curbrightness][dapal[i*3+0]];
+ newPalette[k++] = 0;
+ }
+
+
+ VBE_setPalette(newPalette);
+}
+
+//This is only used by drawmapview.
+static void fillpolygon(int32_t npoints)
+{
+ int32_t z, zz, x1, y1, x2, y2, miny, maxy, y, xinc, cnt;
+ int32_t ox, oy, bx, by, p, day1, day2;
+ short *ptr, *ptr2;
+
+ miny = 0x7fffffff;
+ maxy = 0x80000000;
+ for(z=npoints-1; z>=0; z--)
+ {
+ y = pvWalls[z].cameraSpaceCoo[0][VEC_Y];
+ miny = min(miny,y);
+ maxy = max(maxy,y);
+ }
+ miny = (miny>>12);
+ maxy = (maxy>>12);
+ if (miny < 0) miny = 0;
+ if (maxy >= ydim) maxy = ydim-1;
+ ptr = smost; /* They're pointers! - watch how you optimize this thing */
+ for(y=miny; y<=maxy; y++)
+ {
+ dotp1[y] = ptr;
+ dotp2[y] = ptr+(MAXNODESPERLINE>>1);
+ ptr += MAXNODESPERLINE;
+ }
+
+ for(z=npoints-1; z>=0; z--)
+ {
+ zz = pvWalls[z].screenSpaceCoo[0][VEC_COL];
+ y1 = pvWalls[z] .cameraSpaceCoo[0][VEC_Y];
+ day1 = (y1>>12);
+ y2 = pvWalls[zz].cameraSpaceCoo[0][VEC_Y];
+ day2 = (y2>>12);
+ if (day1 != day2)
+ {
+ x1 = pvWalls[z ].cameraSpaceCoo[0][VEC_X];
+ x2 = pvWalls[zz].cameraSpaceCoo[0][VEC_X];
+ xinc = divscale12(x2-x1,y2-y1);
+ if (day2 > day1)
+ {
+ x1 += mulscale12((day1<<12)+4095-y1,xinc);
+ for(y=day1; y<day2; y++) {
+ *dotp2[y]++ = (x1>>12);
+ x1 += xinc;
+ }
+ }
+ else
+ {
+ x2 += mulscale12((day2<<12)+4095-y2,xinc);
+ for(y=day2; y<day1; y++) {
+ *dotp1[y]++ = (x2>>12);
+ x2 += xinc;
+ }
+ }
+ }
+ }
+
+ globalx1 = mulscale16(globalx1,xyaspect);
+ globaly2 = mulscale16(globaly2,xyaspect);
+
+ oy = miny+1-(ydim>>1);
+ globalposx += oy*globalx1;
+ globalposy += oy*globaly2;
+
+
+
+ ptr = smost;
+ for(y=miny; y<=maxy; y++)
+ {
+ cnt = dotp1[y]-ptr;
+ ptr2 = ptr+(MAXNODESPERLINE>>1);
+ for(z=cnt-1; z>=0; z--)
+ {
+ day1 = 0;
+ day2 = 0;
+ for(zz=z; zz>0; zz--)
+ {
+ if (ptr[zz] < ptr[day1]) day1 = zz;
+ if (ptr2[zz] < ptr2[day2]) day2 = zz;
+ }
+ x1 = ptr[day1];
+ ptr[day1] = ptr[z];
+ x2 = ptr2[day2]-1;
+ ptr2[day2] = ptr2[z];
+ if (x1 > x2) continue;
+
+ if (globalpolytype < 1)
+ {
+ /* maphline */
+ ox = x2+1-(xdim>>1);
+ bx = ox*asm1 + globalposx;
+ by = ox*asm2 - globalposy;
+
+ p = ylookup[y]+x2+frameplace;
+ hlineasm4(x2-x1,globalshade<<8,by,bx,p);
+ }
+ else
+ {
+ /* maphline */
+ ox = x1+1-(xdim>>1);
+ bx = ox*asm1 + globalposx;
+ by = ox*asm2 - globalposy;
+
+ p = ylookup[y]+x1+frameplace;
+ if (globalpolytype == 1)
+ mhline(globalbufplc,bx,(x2-x1)<<16,0L,by,p);
+ else
+ {
+ thline(globalbufplc,bx,(x2-x1)<<16,0L,by,p);
+ transarea += (x2-x1);
+ }
+ }
+ }
+ globalposx += globalx1;
+ globalposy += globaly2;
+ ptr += MAXNODESPERLINE;
+ }
+ faketimerhandler();
+}
+
+
+static int clippoly (int32_t npoints, int32_t clipstat)
+{
+ int32_t z, zz, s1, s2, t, npoints2, start2, z1, z2, z3, z4, splitcnt;
+ int32_t cx1, cy1, cx2, cy2;
+
+ cx1 = windowx1;
+ cy1 = windowy1;
+ cx2 = windowx2+1;
+ cy2 = windowy2+1;
+ cx1 <<= 12;
+ cy1 <<= 12;
+ cx2 <<= 12;
+ cy2 <<= 12;
+
+ if (clipstat&0xa) /* Need to clip top or left */
+ {
+ npoints2 = 0;
+ start2 = 0;
+ z = 0;
+ splitcnt = 0;
+ do
+ {
+ s2 = cx1-pvWalls[z].cameraSpaceCoo[0][VEC_X];
+ do
+ {
+ zz = pvWalls[z].screenSpaceCoo[0][VEC_COL];
+ pvWalls[z].screenSpaceCoo[0][VEC_COL] = -1;
+ s1 = s2;
+ s2 = cx1-pvWalls[zz].cameraSpaceCoo[0][VEC_X];
+ if (s1 < 0){
+ pvWalls[npoints2].cameraSpaceCoo[1][VEC_X] = pvWalls[zz].cameraSpaceCoo[0][VEC_X];
+ pvWalls[npoints2].cameraSpaceCoo[1][VEC_Y] = pvWalls[zz].cameraSpaceCoo[0][VEC_Y];
+ pvWalls[npoints2].screenSpaceCoo[1][VEC_COL] = npoints2+1;
+ npoints2++;
+ }
+
+ if ((s1^s2) < 0){
+ pvWalls[npoints2].cameraSpaceCoo[1][VEC_X] =
+ pvWalls[z].cameraSpaceCoo[0][VEC_X]+scale(pvWalls[zz].cameraSpaceCoo[0][VEC_X]-pvWalls[z].cameraSpaceCoo[0][VEC_X],s1,s1-s2);
+ pvWalls[npoints2].cameraSpaceCoo[1][VEC_Y] =
+ pvWalls[z].cameraSpaceCoo[0][VEC_Y]+scale(pvWalls[zz].cameraSpaceCoo[0][VEC_Y]-pvWalls[z].cameraSpaceCoo[0][VEC_Y],s1,s1-s2);
+
+ if (s1 < 0)
+ bunchWallsList[splitcnt++] = npoints2;
+
+ pvWalls[npoints2].screenSpaceCoo[1][VEC_COL] = npoints2+1;
+ npoints2++;
+ }
+ z = zz;
+ } while (pvWalls[z].screenSpaceCoo[0][VEC_COL] >= 0);
+
+ if (npoints2 >= start2+3)
+ pvWalls[npoints2-1].screenSpaceCoo[1][VEC_COL] = start2, start2 = npoints2;
+ else
+ npoints2 = start2;
+
+ z = 1;
+ while ((z < npoints) && (pvWalls[z].screenSpaceCoo[0][VEC_COL] < 0)) z++;
+ } while (z < npoints);
+ if (npoints2 <= 2) return(0);
+
+ for(z=1; z<splitcnt; z++)
+ for(zz=0; zz<z; zz++)
+ {
+ z1 = bunchWallsList[z];
+ z2 = pvWalls[z1].screenSpaceCoo[1][VEC_COL];
+ z3 = bunchWallsList[zz];
+ z4 = pvWalls[z3].screenSpaceCoo[1][VEC_COL];
+ s1 = klabs(pvWalls[z1].cameraSpaceCoo[1][VEC_X]-pvWalls[z2].cameraSpaceCoo[1][VEC_X])+klabs(pvWalls[z1].cameraSpaceCoo[1][VEC_Y]-pvWalls[z2].cameraSpaceCoo[1][VEC_Y]);
+ s1 += klabs(pvWalls[z3].cameraSpaceCoo[1][VEC_X]-pvWalls[z4].cameraSpaceCoo[1][VEC_X])+klabs(pvWalls[z3].cameraSpaceCoo[1][VEC_Y]-pvWalls[z4].cameraSpaceCoo[1][VEC_Y]);
+ s2 = klabs(pvWalls[z1].cameraSpaceCoo[1][VEC_X]-pvWalls[z4].cameraSpaceCoo[1][VEC_X])+klabs(pvWalls[z1].cameraSpaceCoo[1][VEC_Y]-pvWalls[z4].cameraSpaceCoo[1][VEC_Y]);
+ s2 += klabs(pvWalls[z3].cameraSpaceCoo[1][VEC_X]-pvWalls[z2].cameraSpaceCoo[1][VEC_X])+klabs(pvWalls[z3].cameraSpaceCoo[1][VEC_Y]-pvWalls[z2].cameraSpaceCoo[1][VEC_Y]);
+ if (s2 < s1)
+ {
+ t = pvWalls[bunchWallsList[z]].screenSpaceCoo[1][VEC_COL];
+ pvWalls[bunchWallsList[z]].screenSpaceCoo[1][VEC_COL] = pvWalls[bunchWallsList[zz]].screenSpaceCoo[1][VEC_COL];
+ pvWalls[bunchWallsList[zz]].screenSpaceCoo[1][VEC_COL] = t;
+ }
+ }
+
+
+ npoints = 0;
+ start2 = 0;
+ z = 0;
+ splitcnt = 0;
+ do
+ {
+ s2 = cy1-pvWalls[z].cameraSpaceCoo[1][VEC_Y];
+ do
+ {
+ zz = pvWalls[z].screenSpaceCoo[1][VEC_COL];
+ pvWalls[z].screenSpaceCoo[1][VEC_COL] = -1;
+ s1 = s2;
+ s2 = cy1-pvWalls[zz].cameraSpaceCoo[1][VEC_Y];
+ if (s1 < 0)
+ {
+ pvWalls[npoints].cameraSpaceCoo[0][VEC_X] = pvWalls[z].cameraSpaceCoo[1][VEC_X];
+ pvWalls[npoints].cameraSpaceCoo[0][VEC_Y] = pvWalls[z].cameraSpaceCoo[1][VEC_Y];
+ pvWalls[npoints].screenSpaceCoo[0][VEC_COL] = npoints+1;
+ npoints++;
+ }
+ if ((s1^s2) < 0)
+ {
+ pvWalls[npoints].cameraSpaceCoo[0][VEC_X] = pvWalls[z].cameraSpaceCoo[1][VEC_X]+scale(pvWalls[zz].cameraSpaceCoo[1][VEC_X]-pvWalls[z].cameraSpaceCoo[1][VEC_X],s1,s1-s2);
+ pvWalls[npoints].cameraSpaceCoo[0][VEC_Y] = pvWalls[z].cameraSpaceCoo[1][VEC_Y]+scale(pvWalls[zz].cameraSpaceCoo[1][VEC_Y]-pvWalls[z].cameraSpaceCoo[1][VEC_Y],s1,s1-s2);
+ if (s1 < 0) bunchWallsList[splitcnt++] = npoints;
+ pvWalls[npoints].screenSpaceCoo[0][VEC_COL] = npoints+1;
+ npoints++;
+ }
+ z = zz;
+ } while (pvWalls[z].screenSpaceCoo[1][VEC_COL] >= 0);
+
+ if (npoints >= start2+3)
+ pvWalls[npoints-1].screenSpaceCoo[0][VEC_COL] = start2, start2 = npoints;
+ else
+ npoints = start2;
+
+ z = 1;
+ while ((z < npoints2) && (pvWalls[z].screenSpaceCoo[1][VEC_COL] < 0)) z++;
+ } while (z < npoints2);
+ if (npoints <= 2) return(0);
+
+ for(z=1; z<splitcnt; z++)
+ for(zz=0; zz<z; zz++)
+ {
+ z1 = bunchWallsList[z];
+ z2 = pvWalls[z1].screenSpaceCoo[0][VEC_COL];
+ z3 = bunchWallsList[zz];
+ z4 = pvWalls[z3].screenSpaceCoo[0][VEC_COL];
+ s1 = klabs(pvWalls[z1].cameraSpaceCoo[0][VEC_X]-pvWalls[z2].cameraSpaceCoo[0][VEC_X])+klabs(pvWalls[z1].cameraSpaceCoo[0][VEC_Y]-pvWalls[z2].cameraSpaceCoo[0][VEC_Y]);
+ s1 += klabs(pvWalls[z3].cameraSpaceCoo[0][VEC_X]-pvWalls[z4].cameraSpaceCoo[0][VEC_X])+klabs(pvWalls[z3].cameraSpaceCoo[0][VEC_Y]-pvWalls[z4].cameraSpaceCoo[0][VEC_Y]);
+ s2 = klabs(pvWalls[z1].cameraSpaceCoo[0][VEC_X]-pvWalls[z4].cameraSpaceCoo[0][VEC_X])+klabs(pvWalls[z1].cameraSpaceCoo[0][VEC_Y]-pvWalls[z4].cameraSpaceCoo[0][VEC_Y]);
+ s2 += klabs(pvWalls[z3].cameraSpaceCoo[0][VEC_X]-pvWalls[z2].cameraSpaceCoo[0][VEC_X])+klabs(pvWalls[z3].cameraSpaceCoo[0][VEC_Y]-pvWalls[z2].cameraSpaceCoo[0][VEC_Y]);
+ if (s2 < s1)
+ {
+ t = pvWalls[bunchWallsList[z]].screenSpaceCoo[0][VEC_COL];
+ pvWalls[bunchWallsList[z]].screenSpaceCoo[0][VEC_COL] = pvWalls[bunchWallsList[zz]].screenSpaceCoo[0][VEC_COL];
+ pvWalls[bunchWallsList[zz]].screenSpaceCoo[0][VEC_COL] = t;
+ }
+ }
+ }
+ if (clipstat&0x5) /* Need to clip bottom or right */
+ {
+ npoints2 = 0;
+ start2 = 0;
+ z = 0;
+ splitcnt = 0;
+ do
+ {
+ s2 = pvWalls[z].cameraSpaceCoo[0][VEC_X]-cx2;
+ do
+ {
+ zz = pvWalls[z].screenSpaceCoo[0][VEC_COL];
+ pvWalls[z].screenSpaceCoo[0][VEC_COL] = -1;
+ s1 = s2;
+ s2 = pvWalls[zz].cameraSpaceCoo[0][VEC_X]-cx2;
+ if (s1 < 0)
+ {
+ pvWalls[npoints2].cameraSpaceCoo[1][VEC_X] = pvWalls[z].cameraSpaceCoo[0][VEC_X];
+ pvWalls[npoints2].cameraSpaceCoo[1][VEC_Y] = pvWalls[z].cameraSpaceCoo[0][VEC_Y];
+ pvWalls[npoints2].screenSpaceCoo[1][VEC_COL] = npoints2+1;
+ npoints2++;
+ }
+ if ((s1^s2) < 0)
+ {
+ pvWalls[npoints2].cameraSpaceCoo[1][VEC_X] = pvWalls[z].cameraSpaceCoo[0][VEC_X]+scale(pvWalls[zz].cameraSpaceCoo[0][VEC_X]-pvWalls[z].cameraSpaceCoo[0][VEC_X],s1,s1-s2);
+ pvWalls[npoints2].cameraSpaceCoo[1][VEC_Y] = pvWalls[z].cameraSpaceCoo[0][VEC_Y]+scale(pvWalls[zz].cameraSpaceCoo[0][VEC_Y]-pvWalls[z].cameraSpaceCoo[0][VEC_Y],s1,s1-s2);
+ if (s1 < 0) bunchWallsList[splitcnt++] = npoints2;
+ pvWalls[npoints2].screenSpaceCoo[1][VEC_COL] = npoints2+1;
+ npoints2++;
+ }
+ z = zz;
+ } while (pvWalls[z].screenSpaceCoo[0][VEC_COL] >= 0);
+
+ if (npoints2 >= start2+3)
+ pvWalls[npoints2-1].screenSpaceCoo[1][VEC_COL] = start2, start2 = npoints2;
+ else
+ npoints2 = start2;
+
+ z = 1;
+ while ((z < npoints) && (pvWalls[z].screenSpaceCoo[0][VEC_COL] < 0)) z++;
+ } while (z < npoints);
+ if (npoints2 <= 2) return(0);
+
+ for(z=1; z<splitcnt; z++)
+ for(zz=0; zz<z; zz++)
+ {
+ z1 = bunchWallsList[z];
+ z2 = pvWalls[z1].screenSpaceCoo[1][VEC_COL];
+ z3 = bunchWallsList[zz];
+ z4 = pvWalls[z3].screenSpaceCoo[1][VEC_COL];
+ s1 = klabs(pvWalls[z1].cameraSpaceCoo[1][VEC_X]-pvWalls[z2].cameraSpaceCoo[1][VEC_X])+klabs(pvWalls[z1].cameraSpaceCoo[1][VEC_Y]-pvWalls[z2].cameraSpaceCoo[1][VEC_Y]);
+ s1 += klabs(pvWalls[z3].cameraSpaceCoo[1][VEC_X]-pvWalls[z4].cameraSpaceCoo[1][VEC_X])+klabs(pvWalls[z3].cameraSpaceCoo[1][VEC_Y]-pvWalls[z4].cameraSpaceCoo[1][VEC_Y]);
+ s2 = klabs(pvWalls[z1].cameraSpaceCoo[1][VEC_X]-pvWalls[z4].cameraSpaceCoo[1][VEC_X])+klabs(pvWalls[z1].cameraSpaceCoo[1][VEC_Y]-pvWalls[z4].cameraSpaceCoo[1][VEC_Y]);
+ s2 += klabs(pvWalls[z3].cameraSpaceCoo[1][VEC_X]-pvWalls[z2].cameraSpaceCoo[1][VEC_X])+klabs(pvWalls[z3].cameraSpaceCoo[1][VEC_Y]-pvWalls[z2].cameraSpaceCoo[1][VEC_Y]);
+ if (s2 < s1)
+ {
+ t = pvWalls[bunchWallsList[z]].screenSpaceCoo[1][VEC_COL];
+ pvWalls[bunchWallsList[z]].screenSpaceCoo[1][VEC_COL] = pvWalls[bunchWallsList[zz]].screenSpaceCoo[1][VEC_COL];
+ pvWalls[bunchWallsList[zz]].screenSpaceCoo[1][VEC_COL] = t;
+ }
+ }
+
+
+ npoints = 0;
+ start2 = 0;
+ z = 0;
+ splitcnt = 0;
+ do
+ {
+ s2 = pvWalls[z].cameraSpaceCoo[1][VEC_Y]-cy2;
+ do
+ {
+ zz = pvWalls[z].screenSpaceCoo[1][VEC_COL];
+ pvWalls[z].screenSpaceCoo[1][VEC_COL] = -1;
+ s1 = s2;
+ s2 = pvWalls[zz].cameraSpaceCoo[1][VEC_Y]-cy2;
+ if (s1 < 0)
+ {
+ pvWalls[npoints].cameraSpaceCoo[0][VEC_X] = pvWalls[z].cameraSpaceCoo[1][VEC_X];
+ pvWalls[npoints].cameraSpaceCoo[0][VEC_Y] = pvWalls[z].cameraSpaceCoo[1][VEC_Y];
+ pvWalls[npoints].screenSpaceCoo[0][VEC_COL] = npoints+1;
+ npoints++;
+ }
+ if ((s1^s2) < 0)
+ {
+ pvWalls[npoints].cameraSpaceCoo[0][VEC_X] = pvWalls[z].cameraSpaceCoo[1][VEC_X]+scale(pvWalls[zz].cameraSpaceCoo[1][VEC_X]-pvWalls[z].cameraSpaceCoo[1][VEC_X],s1,s1-s2);
+ pvWalls[npoints].cameraSpaceCoo[0][VEC_Y] = pvWalls[z].cameraSpaceCoo[1][VEC_Y]+scale(pvWalls[zz].cameraSpaceCoo[1][VEC_Y]-pvWalls[z].cameraSpaceCoo[1][VEC_Y],s1,s1-s2);
+ if (s1 < 0) bunchWallsList[splitcnt++] = npoints;
+ pvWalls[npoints].screenSpaceCoo[0][VEC_COL] = npoints+1;
+ npoints++;
+ }
+ z = zz;
+ } while (pvWalls[z].screenSpaceCoo[1][VEC_COL] >= 0);
+
+ if (npoints >= start2+3)
+ pvWalls[npoints-1].screenSpaceCoo[0][VEC_COL] = start2, start2 = npoints;
+ else
+ npoints = start2;
+
+ z = 1;
+ while ((z < npoints2) && (pvWalls[z].screenSpaceCoo[1][VEC_COL] < 0)) z++;
+ } while (z < npoints2);
+ if (npoints <= 2) return(0);
+
+ for(z=1; z<splitcnt; z++)
+ for(zz=0; zz<z; zz++)
+ {
+ z1 = bunchWallsList[z];
+ z2 = pvWalls[z1].screenSpaceCoo[0][VEC_COL];
+ z3 = bunchWallsList[zz];
+ z4 = pvWalls[z3].screenSpaceCoo[0][VEC_COL];
+ s1 = klabs(pvWalls[z1].cameraSpaceCoo[0][VEC_X]-pvWalls[z2].cameraSpaceCoo[0][VEC_X])+klabs(pvWalls[z1].cameraSpaceCoo[0][VEC_Y]-pvWalls[z2].cameraSpaceCoo[0][VEC_Y]);
+ s1 += klabs(pvWalls[z3].cameraSpaceCoo[0][VEC_X]-pvWalls[z4].cameraSpaceCoo[0][VEC_X])+klabs(pvWalls[z3].cameraSpaceCoo[0][VEC_Y]-pvWalls[z4].cameraSpaceCoo[0][VEC_Y]);
+ s2 = klabs(pvWalls[z1].cameraSpaceCoo[0][VEC_X]-pvWalls[z4].cameraSpaceCoo[0][VEC_X])+klabs(pvWalls[z1].cameraSpaceCoo[0][VEC_Y]-pvWalls[z4].cameraSpaceCoo[0][VEC_Y]);
+ s2 += klabs(pvWalls[z3].cameraSpaceCoo[0][VEC_X]-pvWalls[z2].cameraSpaceCoo[0][VEC_X])+klabs(pvWalls[z3].cameraSpaceCoo[0][VEC_Y]-pvWalls[z2].cameraSpaceCoo[0][VEC_Y]);
+ if (s2 < s1)
+ {
+ t = pvWalls[bunchWallsList[z]].screenSpaceCoo[0][VEC_COL];
+ pvWalls[bunchWallsList[z]].screenSpaceCoo[0][VEC_COL] = pvWalls[bunchWallsList[zz]].screenSpaceCoo[0][VEC_COL];
+ pvWalls[bunchWallsList[zz]].screenSpaceCoo[0][VEC_COL] = t;
+ }
+ }
+ }
+ return(npoints);
+}
+
+
+void drawmapview(int32_t dax, int32_t day, int32_t zoome, short ang)
+{
+ walltype *wal;
+ sectortype *sec;
+ spritetype *spr;
+ int32_t tilenum, xoff, yoff, i, j, k, l, cosang, sinang, xspan, yspan;
+ int32_t xrepeat, yrepeat, x, y, x1, y1, x2, y2, x3, y3, x4, y4, bakx1, baky1;
+ int32_t s, w, ox, oy, startwall, cx1, cy1, cx2, cy2;
+ int32_t bakgxvect, bakgyvect, sortnum, gap, npoints;
+ int32_t xvect, yvect, xvect2, yvect2, daslope;
+
+ beforedrawrooms = 0;
+
+
+ //This seems to be dead code.
+ //clearbuf(visitedSectors,(int32_t)((numsectors+31)>>5),0L);
+
+ cx1 = (windowx1<<12);
+ cy1 = (windowy1<<12);
+ cx2 = ((windowx2+1)<<12)-1;
+ cy2 = ((windowy2+1)<<12)-1;
+ zoome <<= 8;
+ bakgxvect = divscale28(sintable[(1536-ang)&2047],zoome);
+ bakgyvect = divscale28(sintable[(2048-ang)&2047],zoome);
+ xvect = mulscale8(sintable[(2048-ang)&2047],zoome);
+ yvect = mulscale8(sintable[(1536-ang)&2047],zoome);
+ xvect2 = mulscale16(xvect,yxaspect);
+ yvect2 = mulscale16(yvect,yxaspect);
+
+ sortnum = 0;
+ for(s=0,sec=&sector[s]; s<numsectors; s++,sec++)
+ if (show2dsector[s>>3]&pow2char[s&7])
+ {
+ npoints = 0;
+ i = 0;
+ startwall = sec->wallptr;
+ for(w=sec->wallnum,wal=&wall[startwall]; w>0; w--,wal++)
+ {
+ ox = wal->x - dax;
+ oy = wal->y - day;
+ x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11);
+ y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11);
+ i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
+ pvWalls[npoints].cameraSpaceCoo[0][VEC_X] = x;
+ pvWalls[npoints].cameraSpaceCoo[0][VEC_Y] = y;
+ pvWalls[npoints].screenSpaceCoo[0][VEC_COL] = wal->point2 - startwall;
+ npoints++;
+ }
+
+ if ((i&0xf0) != 0xf0)
+ continue;
+
+ bakx1 = pvWalls[0].cameraSpaceCoo[0][VEC_X];
+ baky1 = mulscale16(pvWalls[0].cameraSpaceCoo[0][VEC_Y]-(ydim<<11),xyaspect)+(ydim<<11);
+ if (i&0x0f)
+ {
+ npoints = clippoly(npoints,i);
+ if (npoints < 3) continue;
+ }
+
+ /* Collect floor sprites to draw */
+ for(i=headspritesect[s]; i>=0; i=nextspritesect[i])
+ if ((sprite[i].cstat&48) == 32)
+ {
+ if ((sprite[i].cstat&(64+8)) == (64+8)) continue;
+ tsprite[sortnum++].owner = i;
+ }
+
+ //This seems to be dead code.
+ //visitedSectors[s>>3] |= pow2char[s&7];
+
+ globalorientation = (int32_t)sec->floorstat;
+ if ((globalorientation&1) != 0) continue;
+
+ if (palookup[sec->floorpal] != globalpalwritten)
+ {
+ globalpalwritten = palookup[sec->floorpal];
+
+ }
+ globalpicnum = sec->floorpicnum;
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES) globalpicnum = 0;
+ setgotpic(globalpicnum);
+
+ if ((tiles[globalpicnum].dim.width <= 0) ||
+ (tiles[globalpicnum].dim.height <= 0)) continue;
+
+ if ((tiles[globalpicnum].animFlags&192) != 0)
+ globalpicnum += animateoffs(globalpicnum);
+
+ TILE_MakeAvailable(globalpicnum);
+
+ globalbufplc = tiles[globalpicnum].data;
+
+ globalshade = max(min(sec->floorshade,numpalookups-1),0);
+ globvis = globalhisibility;
+ if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+ globalpolytype = 0;
+ if ((globalorientation&64) == 0)
+ {
+ globalposx = dax;
+ globalx1 = bakgxvect;
+ globaly1 = bakgyvect;
+ globalposy = day;
+ globalx2 = bakgxvect;
+ globaly2 = bakgyvect;
+ }
+ else
+ {
+ ox = wall[wall[startwall].point2].x - wall[startwall].x;
+ oy = wall[wall[startwall].point2].y - wall[startwall].y;
+ i = nsqrtasm(ox*ox+oy*oy);
+
+ if (i == 0)
+ continue;
+
+ i = 1048576/i;
+ globalx1 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i);
+ globaly1 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i);
+ ox = (bakx1>>4)-(xdim<<7);
+ oy = (baky1>>4)-(ydim<<7);
+ globalposx = dmulscale28(-oy,globalx1,-ox,globaly1);
+ globalposy = dmulscale28(-ox,globalx1,oy,globaly1);
+ globalx2 = -globalx1;
+ globaly2 = -globaly1;
+
+ daslope = sector[s].floorheinum;
+ i = nsqrtasm(daslope*daslope+16777216);
+ globalposy = mulscale12(globalposy,i);
+ globalx2 = mulscale12(globalx2,i);
+ globaly2 = mulscale12(globaly2,i);
+ }
+ globalxshift = (8-(picsiz[globalpicnum]&15));
+ globalyshift = (8-(picsiz[globalpicnum]>>4));
+ if (globalorientation&8) {
+ globalxshift++;
+ globalyshift++;
+ }
+
+ sethlinesizes(picsiz[globalpicnum]&15,picsiz[globalpicnum]>>4,globalbufplc);
+
+ if ((globalorientation&0x4) > 0)
+ {
+ i = globalposx;
+ globalposx = -globalposy;
+ globalposy = -i;
+ i = globalx2;
+ globalx2 = globaly1;
+ globaly1 = i;
+ i = globalx1;
+ globalx1 = -globaly2;
+ globaly2 = -i;
+ }
+ if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalposx = -globalposx;
+ if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalposy = -globalposy;
+ asm1 = (globaly1<<globalxshift);
+ asm2 = (globalx2<<globalyshift);
+ globalx1 <<= globalxshift;
+ globaly2 <<= globalyshift;
+ globalposx = (globalposx<<(20+globalxshift))+(((int32_t)sec->floorxpanning)<<24);
+ globalposy = (globalposy<<(20+globalyshift))-(((int32_t)sec->floorypanning)<<24);
+
+ fillpolygon(npoints);
+ }
+
+ /* Sort sprite list */
+ gap = 1;
+ while (gap < sortnum) gap = (gap<<1)+1;
+ for(gap>>=1; gap>0; gap>>=1)
+ for(i=0; i<sortnum-gap; i++)
+ for(j=i; j>=0; j-=gap)
+ {
+ if (sprite[tsprite[j].owner].z <= sprite[tsprite[j+gap].owner].z) break;
+ swapshort(&tsprite[j].owner,&tsprite[j+gap].owner);
+ }
+
+ for(s=sortnum-1; s>=0; s--)
+ {
+ spr = &sprite[tsprite[s].owner];
+ if ((spr->cstat&48) == 32)
+ {
+ npoints = 0;
+
+ tilenum = spr->picnum;
+ xoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>8)&255))+((int32_t)spr->xoffset);
+ yoff = (int32_t)((int8_t )((tiles[tilenum].animFlags>>16)&255))+((int32_t)spr->yoffset);
+
+ if ((spr->cstat&4) > 0)
+ xoff = -xoff;
+ if ((spr->cstat&8) > 0)
+ yoff = -yoff;
+
+ k = spr->ang;
+ cosang = sintable[(k+512)&2047];
+ sinang = sintable[k];
+ xspan = tiles[tilenum].dim.width;
+ xrepeat = spr->xrepeat;
+ yspan = tiles[tilenum].dim.height;
+ yrepeat = spr->yrepeat;
+
+ ox = ((xspan>>1)+xoff)*xrepeat;
+ oy = ((yspan>>1)+yoff)*yrepeat;
+ x1 = spr->x + mulscale(sinang,ox,16) + mulscale(cosang,oy,16);
+ y1 = spr->y + mulscale(sinang,oy,16) - mulscale(cosang,ox,16);
+ l = xspan*xrepeat;
+ x2 = x1 - mulscale(sinang,l,16);
+ y2 = y1 + mulscale(cosang,l,16);
+ l = yspan*yrepeat;
+ k = -mulscale(cosang,l,16);
+ x3 = x2+k;
+ x4 = x1+k;
+ k = -mulscale(sinang,l,16);
+ y3 = y2+k;
+ y4 = y1+k;
+
+ pvWalls[0].screenSpaceCoo[0][VEC_COL] = 1;
+ pvWalls[1].screenSpaceCoo[0][VEC_COL] = 2;
+ pvWalls[2].screenSpaceCoo[0][VEC_COL] = 3;
+ pvWalls[3].screenSpaceCoo[0][VEC_COL] = 0;
+ npoints = 4;
+
+ i = 0;
+
+ ox = x1 - dax;
+ oy = y1 - day;
+ x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11);
+ y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11);
+ i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
+ pvWalls[0].cameraSpaceCoo[0][VEC_X] = x;
+ pvWalls[0].cameraSpaceCoo[0][VEC_Y] = y;
+
+ ox = x2 - dax;
+ oy = y2 - day;
+ x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11);
+ y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11);
+ i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
+ pvWalls[1].cameraSpaceCoo[0][VEC_X] = x;
+ pvWalls[1].cameraSpaceCoo[0][VEC_Y] = y;
+
+ ox = x3 - dax;
+ oy = y3 - day;
+ x = dmulscale16(ox,xvect,-oy,yvect) + (xdim<<11);
+ y = dmulscale16(oy,xvect2,ox,yvect2) + (ydim<<11);
+ i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
+ pvWalls[2].cameraSpaceCoo[0][VEC_X] = x;
+ pvWalls[2].cameraSpaceCoo[0][VEC_Y] = y;
+
+ x = pvWalls[0].cameraSpaceCoo[0][VEC_X]+pvWalls[2].cameraSpaceCoo[0][VEC_X]-pvWalls[1].cameraSpaceCoo[0][VEC_X];
+ y = pvWalls[3].cameraSpaceCoo[0][VEC_Y]+pvWalls[2].cameraSpaceCoo[0][VEC_Y]-pvWalls[1].cameraSpaceCoo[0][VEC_Y];
+ i |= getclipmask(x-cx1,cx2-x,y-cy1,cy2-y);
+ pvWalls[3].cameraSpaceCoo[0][VEC_X] = x;
+ pvWalls[3].cameraSpaceCoo[0][VEC_Y] = y;
+
+ if ((i&0xf0) != 0xf0) continue;
+ bakx1 = pvWalls[0].cameraSpaceCoo[0][VEC_X];
+ baky1 = mulscale16(pvWalls[0].cameraSpaceCoo[0][VEC_Y]-(ydim<<11),xyaspect)+(ydim<<11);
+ if (i&0x0f)
+ {
+ npoints = clippoly(npoints,i);
+ if (npoints < 3) continue;
+ }
+
+ globalpicnum = spr->picnum;
+ if ((uint32_t)globalpicnum >= (uint32_t)MAXTILES)
+ globalpicnum = 0;
+ setgotpic(globalpicnum);
+
+ if ((tiles[globalpicnum].dim.width <= 0) ||
+ (tiles[globalpicnum].dim.height <= 0))
+ continue;
+
+ if ((tiles[globalpicnum].animFlags&192) != 0)
+ globalpicnum += animateoffs(globalpicnum);
+
+ TILE_MakeAvailable(globalpicnum);
+
+ globalbufplc = tiles[globalpicnum].data;
+ if ((sector[spr->sectnum].ceilingstat&1) > 0)
+ globalshade = ((int32_t)sector[spr->sectnum].ceilingshade);
+ else
+ globalshade = ((int32_t)sector[spr->sectnum].floorshade);
+ globalshade = max(min(globalshade+spr->shade+6,numpalookups-1),0);
+ asm3 = (int32_t) FP_OFF(palookup[spr->pal]+(globalshade<<8));
+ globvis = globalhisibility;
+ if (sec->visibility != 0) globvis = mulscale4(globvis,(int32_t)((uint8_t )(sec->visibility+16)));
+ globalpolytype = ((spr->cstat&2)>>1)+1;
+
+ /* relative alignment stuff */
+ ox = x2-x1;
+ oy = y2-y1;
+ i = ox*ox+oy*oy;
+ if (i == 0) continue;
+ i = (65536*16384)/i;
+ globalx1 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i);
+ globaly1 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i);
+ ox = y1-y4;
+ oy = x4-x1;
+ i = ox*ox+oy*oy;
+ if (i == 0) continue;
+ i = (65536*16384)/i;
+ globalx2 = mulscale10(dmulscale10(ox,bakgxvect,oy,bakgyvect),i);
+ globaly2 = mulscale10(dmulscale10(ox,bakgyvect,-oy,bakgxvect),i);
+
+ ox = picsiz[globalpicnum];
+ oy = ((ox>>4)&15);
+ ox &= 15;
+ if (pow2long[ox] != xspan)
+ {
+ ox++;
+ globalx1 = mulscale(globalx1,xspan,ox);
+ globaly1 = mulscale(globaly1,xspan,ox);
+ }
+
+ bakx1 = (bakx1>>4)-(xdim<<7);
+ baky1 = (baky1>>4)-(ydim<<7);
+ globalposx = dmulscale28(-baky1,globalx1,-bakx1,globaly1);
+ globalposy = dmulscale28(bakx1,globalx2,-baky1,globaly2);
+
+ if ((spr->cstat&2) == 0)
+ msethlineshift(ox,oy);
+ else
+ tsethlineshift(ox,oy);
+
+ if ((spr->cstat&0x4) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalposx = -globalposx;
+ asm1 = (globaly1<<2);
+ globalx1 <<= 2;
+ globalposx <<= (20+2);
+ asm2 = (globalx2<<2);
+ globaly2 <<= 2;
+ globalposy <<= (20+2);
+
+ fillpolygon(npoints);
+ }
+ }
+}
+
+
+void clearview(int32_t dacol)
+{
+ int32_t p, y, dx;
+
+ if (qsetmode != 200) return;
+
+ dx = windowx2-windowx1+1;
+ dacol += (dacol<<8);
+ dacol += (dacol<<16);
+
+ p = frameplace+ylookup[windowy1]+windowx1;
+ for(y=windowy1; y<=windowy2; y++)
+ {
+ clearbufbyte((void *)p,dx,dacol);
+ p += ylookup[1];
+ }
+ faketimerhandler();
+}
+
+
+void clearallviews(int32_t dacol)
+{
+ int32_t i;
+
+ if (qsetmode != 200) return;
+ dacol += (dacol<<8);
+ dacol += (dacol<<16);
+
+ switch(vidoption)
+ {
+ case 1:
+ for(i=0; i<numpages; i++)
+ {
+
+ clearbufbyte((void *)frameplace,imageSize,0L);
+ }
+
+ case 2:
+ clearbuf((void *)frameplace,(xdim*ydim)>>2,0L);
+ break;
+ }
+ faketimerhandler();
+}
+
+
+void plotpixel(int32_t x, int32_t y, uint8_t col)
+{
+ drawpixel(ylookup[y]+x+frameplace,(int32_t)col);
+}
+
+
+uint8_t getpixel(int32_t x, int32_t y)
+{
+ return(readpixel(ylookup[y]+x+frameplace));
+}
+
+/* MUST USE RESTOREFORDRAWROOMS AFTER DRAWING */
+int32_t setviewcnt = 0;
+int32_t bakvidoption[4];
+uint8_t* bakframeplace[4];
+int32_t bakxsiz[4], bakysiz[4];
+int32_t bakwindowx1[4], bakwindowy1[4];
+int32_t bakwindowx2[4], bakwindowy2[4];
+
+void setviewback(void)
+{
+ int32_t i, j, k;
+
+ if (setviewcnt <= 0) return;
+ setviewcnt--;
+
+ setview(bakwindowx1[setviewcnt],bakwindowy1[setviewcnt],
+ bakwindowx2[setviewcnt],bakwindowy2[setviewcnt]);
+ copybufbyte(&bakumost[windowx1],&startumost[windowx1],(windowx2-windowx1+1)*sizeof(startumost[0]));
+ copybufbyte(&bakdmost[windowx1],&startdmost[windowx1],(windowx2-windowx1+1)*sizeof(startdmost[0]));
+ vidoption = bakvidoption[setviewcnt];
+ frameplace = bakframeplace[setviewcnt];
+ if (setviewcnt == 0)
+ k = bakxsiz[0];
+ else
+ k = max(bakxsiz[setviewcnt-1],bakxsiz[setviewcnt]);
+ j = 0;
+ for(i=0; i<=k; i++) ylookup[i] = j, j += bytesperline;
+ setBytesPerLine(bytesperline);
+}
+
+
+
+
+
+void preparemirror(int32_t dax, int32_t day, int32_t daz,
+ short daang, int32_t dahoriz, short dawall,
+ short dasector, int32_t *tposx, int32_t *tposy,
+ short *tang)
+{
+ int32_t i, j, x, y, dx, dy;
+
+ x = wall[dawall].x;
+ dx = wall[wall[dawall].point2].x-x;
+ y = wall[dawall].y;
+ dy = wall[wall[dawall].point2].y-y;
+ j = dx*dx + dy*dy;
+ if (j == 0) return;
+ i = (((dax-x)*dx + (day-y)*dy)<<1);
+ *tposx = (x<<1) + scale(dx,i,j) - dax;
+ *tposy = (y<<1) + scale(dy,i,j) - day;
+ *tang = (((getangle(dx,dy)<<1)-daang)&2047);
+
+ inpreparemirror = 1;
+}
+
+
+void completemirror(void)
+{
+ int32_t i, dy;
+ intptr_t p;
+
+ /* Can't reverse with uninitialized data */
+ if (inpreparemirror) {
+ inpreparemirror = 0;
+ return;
+ }
+ if (mirrorsx1 > 0) mirrorsx1--;
+ if (mirrorsx2 < windowx2-windowx1-1) mirrorsx2++;
+ if (mirrorsx2 < mirrorsx1) return;
+
+ transarea += (mirrorsx2-mirrorsx1)*(windowy2-windowy1);
+
+ p = frameplace+ylookup[windowy1+mirrorsy1]+windowx1+mirrorsx1;
+ i = windowx2-windowx1-mirrorsx2-mirrorsx1;
+ mirrorsx2 -= mirrorsx1;
+ // FIX_00085: Optimized Video driver. FPS increases by +20%.
+ for(dy=mirrorsy2-mirrorsy1-1; dy>=0; dy--)
+ {
+ copybufbyte((void *)(p),tempbuf,mirrorsx2+1);
+ tempbuf[mirrorsx2] = tempbuf[mirrorsx2-1];
+ copybufreverse(&tempbuf[mirrorsx2],(void *)(p+i),mirrorsx2+1);
+ p += ylookup[1];
+ faketimerhandler();
+ }
+}
+
+
+int sectorofwall(short theline)
+{
+ int32_t i, gap;
+
+ if ((theline < 0) || (theline >= numwalls)) return(-1);
+ i = wall[theline].nextwall;
+ if (i >= 0) return(wall[i].nextsector);
+
+ gap = (numsectors>>1);
+ i = gap;
+ while (gap > 1)
+ {
+ gap >>= 1;
+ if (sector[i].wallptr < theline) i += gap;
+ else i -= gap;
+ }
+ while (sector[i].wallptr > theline) i--;
+ while (sector[i].wallptr+sector[i].wallnum <= theline) i++;
+
+ return(i);
+}
+
+
+int getceilzofslope(short sectnum, int32_t dax, int32_t day)
+{
+ int32_t dx, dy, i, j;
+ walltype *wal;
+
+ if (!(sector[sectnum].ceilingstat&2)) return(sector[sectnum].ceilingz);
+ wal = &wall[sector[sectnum].wallptr];
+ dx = wall[wal->point2].x-wal->x;
+ dy = wall[wal->point2].y-wal->y;
+ i = (nsqrtasm(dx*dx+dy*dy)<<5);
+ if (i == 0) return(sector[sectnum].ceilingz);
+ j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x);
+ return(sector[sectnum].ceilingz+scale(sector[sectnum].ceilingheinum,j,i));
+}
+
+
+int getflorzofslope(short sectnum, int32_t dax, int32_t day)
+{
+ int32_t dx, dy, i, j;
+ walltype *wal;
+
+ if (!(sector[sectnum].floorstat&2))
+ return(sector[sectnum].floorz);
+
+ wal = &wall[sector[sectnum].wallptr];
+ dx = wall[wal->point2].x-wal->x;
+ dy = wall[wal->point2].y-wal->y;
+ i = (nsqrtasm(dx*dx+dy*dy)<<5);
+
+ if (i == 0)
+ return(sector[sectnum].floorz);
+
+ j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x);
+
+ return(sector[sectnum].floorz+scale(sector[sectnum].floorheinum,j,i));
+}
+
+/*
+ FCS:
+
+ Output the ceiling and floor Z coordinate in the two last parameters for given:
+ sectorNumber and worldspace (coordinate X,Y).
+
+ If the sector is flat, this is jsut a lookup. But if either the floor/ceiling have
+ a slope it requires more calculation
+
+ */
+void getzsofslope(short sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz)
+{
+ int32_t dx, dy, i, j;
+ walltype *wal, *wal2;
+ sectortype *sec;
+
+ sec = &sector[sectnum];
+ *ceilz = sec->ceilingz;
+ *florz = sec->floorz;
+
+ //If the sector has a slopped ceiling or a slopped floor then it needs more calculation.
+ if ((sec->ceilingstat|sec->floorstat)&2)
+ {
+ wal = &wall[sec->wallptr];
+ wal2 = &wall[wal->point2];
+ dx = wal2->x-wal->x;
+ dy = wal2->y-wal->y;
+ i = (nsqrtasm(dx*dx+dy*dy)<<5);
+ if (i == 0) return;
+ j = dmulscale3(dx,day-wal->y,-dy,dax-wal->x);
+
+ if (sec->ceilingstat&2)
+ *ceilz = (*ceilz)+scale(sec->ceilingheinum,j,i);
+ if (sec->floorstat&2)
+ *florz = (*florz)+scale(sec->floorheinum,j,i);
+ }
+}
+
+
+void alignceilslope(short dasect, int32_t x, int32_t y, int32_t z)
+{
+ int32_t i, dax, day;
+ walltype *wal;
+
+ wal = &wall[sector[dasect].wallptr];
+ dax = wall[wal->point2].x-wal->x;
+ day = wall[wal->point2].y-wal->y;
+
+ i = (y-wal->y)*dax - (x-wal->x)*day;
+ if (i == 0) return;
+ sector[dasect].ceilingheinum = scale((z-sector[dasect].ceilingz)<<8,
+ nsqrtasm(dax*dax+day*day),i);
+
+ if (sector[dasect].ceilingheinum == 0) sector[dasect].ceilingstat &= ~2;
+ else sector[dasect].ceilingstat |= 2;
+}
+
+
+void alignflorslope(short dasect, int32_t x, int32_t y, int32_t z)
+{
+ int32_t i, dax, day;
+ walltype *wal;
+
+ wal = &wall[sector[dasect].wallptr];
+ dax = wall[wal->point2].x-wal->x;
+ day = wall[wal->point2].y-wal->y;
+
+ i = (y-wal->y)*dax - (x-wal->x)*day;
+ if (i == 0) return;
+ sector[dasect].floorheinum = scale((z-sector[dasect].floorz)<<8,
+ nsqrtasm(dax*dax+day*day),i);
+
+ if (sector[dasect].floorheinum == 0) sector[dasect].floorstat &= ~2;
+ else sector[dasect].floorstat |= 2;
+}
+
+/*
+ FCS:
+ Search for ???
+*/
+int loopnumofsector(short sectnum, short wallnum)
+{
+ int32_t i, numloops, startwall, endwall;
+
+ numloops = 0;
+
+ startwall = sector[sectnum].wallptr;
+ endwall = startwall + sector[sectnum].wallnum;
+
+ for(i=startwall; i<endwall; i++)
+ {
+ if (i == wallnum)
+ return(numloops);
+
+ if (wall[i].point2 < i)
+ numloops++;
+ }
+ return(-1);
+}
+
+
+void setfirstwall(short sectnum, short newfirstwall)
+{
+ int32_t i, j, k, numwallsofloop;
+ int32_t startwall, endwall, danumwalls, dagoalloop;
+
+ startwall = sector[sectnum].wallptr;
+ danumwalls = sector[sectnum].wallnum;
+ endwall = startwall+danumwalls;
+ if ((newfirstwall < startwall) || (newfirstwall >= startwall+danumwalls)) return;
+ for(i=0; i<danumwalls; i++)
+ memcpy(&wall[i+numwalls],&wall[i+startwall],sizeof(walltype));
+
+ numwallsofloop = 0;
+ i = newfirstwall;
+ do
+ {
+ numwallsofloop++;
+ i = wall[i].point2;
+ } while (i != newfirstwall);
+
+ /* Put correct loop at beginning */
+ dagoalloop = loopnumofsector(sectnum,newfirstwall);
+ if (dagoalloop > 0)
+ {
+ j = 0;
+ while (loopnumofsector(sectnum,j+startwall) != dagoalloop) j++;
+ for(i=0; i<danumwalls; i++)
+ {
+ k = i+j;
+ if (k >= danumwalls) k -= danumwalls;
+ memcpy(&wall[startwall+i],&wall[numwalls+k],sizeof(walltype));
+
+ wall[startwall+i].point2 += danumwalls-startwall-j;
+ if (wall[startwall+i].point2 >= danumwalls)
+ wall[startwall+i].point2 -= danumwalls;
+ wall[startwall+i].point2 += startwall;
+ }
+ newfirstwall += danumwalls-j;
+ if (newfirstwall >= startwall+danumwalls) newfirstwall -= danumwalls;
+ }
+
+ for(i=0; i<numwallsofloop; i++)
+ memcpy(&wall[i+numwalls],&wall[i+startwall],sizeof(walltype));
+ for(i=0; i<numwallsofloop; i++)
+ {
+ k = i+newfirstwall-startwall;
+ if (k >= numwallsofloop) k -= numwallsofloop;
+ memcpy(&wall[startwall+i],&wall[numwalls+k],sizeof(walltype));
+
+ wall[startwall+i].point2 += numwallsofloop-newfirstwall;
+ if (wall[startwall+i].point2 >= numwallsofloop)
+ wall[startwall+i].point2 -= numwallsofloop;
+ wall[startwall+i].point2 += startwall;
+ }
+
+ for(i=startwall; i<endwall; i++)
+ if (wall[i].nextwall >= 0) wall[wall[i].nextwall].nextwall = i;
+}
+
+/* end of engine.c ... */
+
+
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/engine.h b/apps/plugins/sdl/progs/duke3d/Engine/src/engine.h
new file mode 100644
index 0000000000..d209396ab2
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/engine.h
@@ -0,0 +1,164 @@
+/*
+ * A list of all symbols exported from engine.c for a game's use.
+ *
+ * Put together by Ryan C. Gordon (icculus@clutteredmind.org)
+ *
+ * Please do NOT harrass Ken Silverman about any code modifications
+ * (including this file) to BUILD.
+ */
+
+/*
+ * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
+ * Ken Silverman's official web site: "http://www.advsys.net/ken"
+ * See the included license file "BUILDLIC.TXT" for license info.
+ * This file IS NOT A PART OF Ken Silverman's original release
+ */
+
+#ifndef _INCLUDE_ENGINE_H_
+#define _INCLUDE_ENGINE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ENGINE_DIR "/.rockbox/duke3d/"
+
+//#define SUPERBUILD /* don't touch this. */
+
+/*
+ * this must be implemented by every program that uses the BUILD engine.
+ * engine.c calls this function in several places.
+ * See Ken's test game (in game.c), and his editor (in bstub.c) for examples.
+ */
+void faketimerhandler(void);
+
+/*
+ * exported engine functions, in absolutely no particular order.
+ * See build.txt, build2.txt...and anything else with a .txt extention for
+ * information on using these functions that may or may not be accurate. :)
+ */
+int initmouse(void);
+int setgamemode(uint8_t davidoption, int32_t daxdim, int32_t daydim);
+int getceilzofslope(int16_t sectnum, int32_t dax, int32_t day);
+int getflorzofslope(int16_t sectnum, int32_t dax, int32_t day);
+void getzsofslope(int16_t sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz);
+void setaspect(int32_t daxrange, int32_t daaspect);
+int insertsprite(int16_t sectnum, int16_t statnum);
+void updatesector(int32_t x, int32_t y, int16_t *sectnum);
+int lastwall(int16_t point);
+void initspritelists(void);
+int deletesprite(int16_t spritenum);
+int insertspritesect(int16_t sectnum);
+int deletespritesect(int16_t deleteme);
+int deletespritestat (int16_t deleteme);
+int insertspritestat(int16_t statnum);
+int changespritesect(int16_t spritenum, int16_t newsectnum);
+int changespritestat(int16_t spritenum, int16_t newstatnum);
+void loadtile(int16_t tilenume);
+
+
+void nextpage(void);
+void drawrooms(int32_t daposx, int32_t daposy, int32_t daposz,int16_t daang, int32_t dahoriz, int16_t dacursectnum);
+int loadboard(char *filename, int32_t *daposx, int32_t *daposy,int32_t *daposz, int16_t *daang, int16_t *dacursectnum);
+void drawmasks(void);
+void printext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol,char name[82], uint8_t fontsize);
+
+void initengine(void);
+void uninitengine(void);
+
+int loadpics(char *filename, char * gamedir);
+int saveboard(char *filename, int32_t *daposx, int32_t *daposy, int32_t *daposz,int16_t *daang, int16_t *dacursectnum);
+void plotpixel(int32_t x, int32_t y, uint8_t col);
+uint8_t getpixel(int32_t x, int32_t y);
+void setbrightness(uint8_t dabrightness, uint8_t *dapal);
+int screencapture(char *filename, uint8_t inverseit);
+void getmousevalues(int16_t *mousx, int16_t *mousy, int16_t *bstatus);
+int clipmove (int32_t *x, int32_t *y, int32_t *z, int16_t *sectnum, int32_t xvect,int32_t yvect, int32_t walldist, int32_t ceildist,int32_t flordist, uint32_t cliptype);
+void getzrange(int32_t x, int32_t y, int32_t z, int16_t sectnum,int32_t *ceilz, int32_t *ceilhit, int32_t *florz, int32_t *florhit,int32_t walldist, uint32_t cliptype);
+int getangle(int32_t xvect, int32_t yvect);
+void alignceilslope(int16_t dasect, int32_t x, int32_t y, int32_t z);
+void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z);
+int hitscan(int32_t xs, int32_t ys, int32_t zs, int16_t sectnum,
+ int32_t vx, int32_t vy, int32_t vz,
+ int16_t *hitsect, int16_t *hitwall, int16_t *hitsprite,
+ int32_t *hitx, int32_t *hity, int32_t *hitz, uint32_t cliptype);
+int inside (int32_t x, int32_t y, int16_t sectnum);
+void setfirstwall(int16_t sectnum, int16_t newfirstwall);
+void rotatepoint(int32_t xpivot, int32_t ypivot, int32_t x, int32_t y, int16_t daang,
+ int32_t *x2, int32_t *y2);
+int drawtilescreen(int32_t pictopleft, int32_t picbox);
+void clearview(int32_t dacol);
+void clearallviews(int32_t dacol);
+void draw2dgrid(int32_t posxe, int32_t posye, int16_t ange, int32_t zoome,int16_t gride);
+void draw2dscreen(int32_t posxe, int32_t posye, int16_t ange, int32_t zoome,int16_t gride);
+int sectorofwall(int16_t theline);
+int setsprite(int16_t spritenum, int32_t newx, int32_t newy, int32_t newz);
+void dragpoint(int16_t pointhighlight, int32_t dax, int32_t day);
+int ksqrt(int32_t num);
+int loopnumofsector(int16_t sectnum, int16_t wallnum);
+int cansee(int32_t x1, int32_t y1, int32_t z1, int16_t sect1,int32_t x2, int32_t y2, int32_t z2, int16_t sect2);
+int lintersect(int32_t x1, int32_t y1, int32_t z1, int32_t x2, int32_t y2, int32_t z2, int32_t x3, int32_t y3, int32_t x4, int32_t y4, int32_t *intx,int32_t *inty, int32_t *intz);
+int rintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx, int32_t vy, int32_t vz,
+ int32_t x3, int32_t y3, int32_t x4, int32_t y4, int32_t *intx,
+ int32_t *inty, int32_t *intz);
+uint8_t* allocatepermanenttile(int16_t tilenume, int32_t xsiz, int32_t ysiz);
+void drawline256 (int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t col);
+void copytilepiece(int32_t tilenume1, int32_t sx1, int32_t sy1, int32_t xsiz, int32_t ysiz,
+ int32_t tilenume2, int32_t sx2, int32_t sy2);
+int nextsectorneighborz(int16_t sectnum, int32_t thez,
+ int16_t topbottom, int16_t direction);
+int neartag(int32_t xs, int32_t ys, int32_t zs, int16_t sectnum, int16_t ange,
+ int16_t *neartagsector, int16_t *neartagwall, int16_t *neartagsprite,
+ int32_t *neartaghitdist, int32_t neartagrange, uint8_t tagsearch);
+int pushmove(int32_t *x, int32_t *y, int32_t *z, int16_t *sectnum,
+ int32_t walldist, int32_t ceildist, int32_t flordist,
+ uint32_t cliptype);
+
+int krand(void);
+
+void flushperms(void);
+void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
+ int8_t dashade, uint8_t dapalnum, uint8_t dastat,
+ int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2);
+void makepalookup(int32_t palnum, uint8_t *remapbuf, int8_t r,
+ int8_t g, int8_t b, uint8_t dastat);
+void drawmapview(int32_t dax, int32_t day, int32_t zoome, int16_t ang);
+void setview(int32_t x1, int32_t y1, int32_t x2, int32_t y2);
+void setviewtotile(int16_t tilenume, int32_t xsiz, int32_t ysiz);
+void setviewback(void);
+void squarerotatetile(int16_t tilenume);
+void preparemirror(int32_t dax, int32_t day, int32_t daz,
+ int16_t daang, int32_t dahoriz, int16_t dawall,
+ int16_t dasector, int32_t *tposx, int32_t *tposy,
+ short *tang);
+void completemirror(void);
+int clipinsidebox(int32_t x, int32_t y, int16_t wallnum, int32_t walldist);
+
+#include "cache.h"
+#include "filesystem.h"
+#include "display.h"
+#include "fixedPoint_math.h"
+#include "tiles.h"
+#include "network.h"
+
+
+//Exported for tile module
+ extern int32_t setviewcnt;
+ extern int32_t bakvidoption[4];
+ extern uint8_t* bakframeplace[4];
+ extern int32_t bakxsiz[4], bakysiz[4];
+ extern int32_t bakwindowx1[4], bakwindowy1[4];
+ extern int32_t bakwindowx2[4], bakwindowy2[4];
+ extern uint8_t picsiz[MAXTILES], tilefilenum[MAXTILES];
+ extern int16_t bakumost[MAXXDIM+1], bakdmost[MAXXDIM+1];
+ extern int32_t numtilefiles, artfil , artfilnum, artfilplc;
+ extern int32_t pow2long[32];
+ extern int32_t artsize , cachesize ;
+ extern int32_t tilefileoffs[MAXTILES];
+ extern int32_t totalclocklock;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/filesystem.c b/apps/plugins/sdl/progs/duke3d/Engine/src/filesystem.c
new file mode 100644
index 0000000000..641d954e0a
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Engine/src/filesystem.c
@@ -0,0 +1,877 @@
+//
+// filesystem.c
+// Duke3D
+//
+// Created by fabien sanglard on 12-12-19.
+// Copyright (c) 2012 fabien sanglard. All rights reserved.
+//
+
+#include "filesystem.h"
+
+#include "platform.h"
+#include "cache.h"
+#include "fixedPoint_math.h"
+#include "../../Game/src/global.h"
+
+extern char game_dir[512];
+
+//The multiplayer module in game.dll needs direct access to the crc32 (sic).
+int32_t groupefil_crc32[MAXGROUPFILES];
+
+
+// A typical GRP index entry:
+// - 12 bytes for filename
+// - 4 for filesize
+typedef uint8_t grpIndexEntry_t[16];
+
+typedef struct grpArchive_s{
+
+ int32_t numFiles ;//Number of files in the archive.
+ grpIndexEntry_t *gfilelist ;//Array containing the filenames.
+ int32_t *fileOffsets ;//Array containing the file offsets.
+ int32_t *filesizes ;//Array containing the file offsets.
+ int fileDescriptor ;//The fd used for open,read operations.
+ uint32_t crc32 ;//Hash to recognize GRP: Duke Shareware, Duke plutonimum etc...
+
+ int cache_len; // valid if cached == 1
+ int cached; // 0 = not cached, 1 = partial, 2 = full
+ uint8_t *data; // entire file in RAM
+} __attribute__((packed)) grpArchive_t;
+
+//All GRP opened are in this structure
+typedef struct grpSet_s{
+ grpArchive_t archives[MAXGROUPFILES];
+ int32_t num;
+} __attribute__((packed)) grpSet_t;
+
+// Marking it static gurantee not only invisility outside module
+// but also that the content will be set to 0.
+static grpSet_t grpSet;
+
+int32_t filelength(int32_t fd);
+
+int32_t initgroupfile(const char *filename)
+{
+ uint8_t buf[16] ;
+ int32_t i, j, k ;
+ grpArchive_t* archive ;
+
+
+
+ printf("Loading %s ...\n", filename);
+
+ if (grpSet.num == MAXGROUPFILES){
+ printf("Error: Unable to open an extra GRP archive <= No more slot available.\n");
+ return(-1);
+ }
+
+ archive = &grpSet.archives[grpSet.num];
+
+ //Init the slot
+ memset(archive, 0, sizeof(grpArchive_t));
+
+ //groupfil_memory[numgroupfiles] = NULL; // addresses of raw GRP files in memory
+ //groupefil_crc32[numgroupfiles] = 0;
+
+ archive->fileDescriptor = open(filename,O_BINARY|O_RDONLY);
+
+ if (archive->fileDescriptor < 0){
+ printf("Error: Unable to open file %s.\n",filename);
+
+ exit(0);
+ }
+
+
+ read(archive->fileDescriptor,buf,16);
+
+ //FCS : The ".grp" file format is just a collection of a lot of files stored into 1 big one.
+ //KS doc: I tried to make the format as simple as possible: The first 12 bytes contains my name,
+ //"KenSilverman". The next 4 bytes is the number of files that were compacted into the
+ //group file. Then for each file, there is a 16 byte structure, where the first 12
+ //bytes are the filename, and the last 4 bytes are the file's size. The rest of the
+ //group file is just the raw data packed one after the other in the same order as the list
+ //of files. - ken
+
+ // Check the magic number (12 bytes header).
+ if ((buf[0] != 'K') || (buf[1] != 'e') || (buf[2] != 'n') ||
+ (buf[3] != 'S') || (buf[4] != 'i') || (buf[5] != 'l') ||
+ (buf[6] != 'v') || (buf[7] != 'e') || (buf[8] != 'r') ||
+ (buf[9] != 'm') || (buf[10] != 'a') || (buf[11] != 'n')){
+ printf("Error: File %s is not a GRP archive.\n",filename);
+ return(-1);
+ }
+
+ // The next 4 bytes of the header feature the number of files in the GRP archive.
+ archive->numFiles = BUILDSWAP_INTEL32(*((int32_t *)&buf[12]));
+
+
+ archive->gfilelist = kmalloc(archive->numFiles * sizeof(grpIndexEntry_t));
+ archive->fileOffsets = kmalloc(archive->numFiles * sizeof(int32_t));
+ archive->filesizes = kmalloc(archive->numFiles * sizeof(int32_t));
+
+ // Load the full index 16 bytes per file (12bytes for name + 4 bytes for the size).
+ read(archive->fileDescriptor,archive->gfilelist, archive->numFiles * 16);
+
+ //Initialize all file offset and pointers.
+ j = 12 + 4 + archive->numFiles * sizeof(grpIndexEntry_t);
+ for(i=0;i<archive->numFiles;i++){
+
+ k = BUILDSWAP_INTEL32(*((int32_t *)&archive->gfilelist[i][12])); // get size
+
+ // Now that the filesize has been read, we can replace it with '0' and hence have a
+ // valid, null terminated character string that will be usable.
+ archive->gfilelist[i][12] = '\0';
+ archive->filesizes[i] = k;
+ archive->fileOffsets[i] = j; // absolute offset list of all files.
+ j += k;
+ }
+ //archive->fileOffsets[archive->numFiles-1] = j;
+
+
+ // Compute CRC32 of the whole grp and implicitely caches the GRP in memory through windows caching service.
+ // Rewind the fileDescriptor
+ lseek(archive->fileDescriptor, 0, SEEK_SET);
+
+ //i = 1000000;
+ //groupfil_memory[numgroupfiles] = malloc(i);
+
+ //Load the full GRP in RAM.
+
+ int total = filelength(archive->fileDescriptor);
+
+#define CRC_BUFLEN 1024*128
+
+ /* Atomic Edition won't fit */
+ if(total > MEMORYSIZE / 2 * 1024 * 1024)
+ {
+#if MEMORYSIZE > 32
+ archive->cached = 1;
+ archive->cache_len = 24 * 1024 * 1024; /* arbitrary, but must be multiple of CRC_BUFLEN (currently 1024*128) */
+ assert(archive->cache_len % CRC_BUFLEN == 0);
+ archive->data = malloc(archive->cache_len);
+#else
+ archive->cached = 0;
+ archive->data = 0;
+#endif
+ }
+ else
+ {
+ archive->data = malloc(total);
+ archive->cached = archive->data != NULL ? 2 : 0;
+ }
+
+ switch(archive->cached)
+ {
+ case 2:
+ printf("Caching complete GRP in RAM (%d KB)\n", total / 1024);
+ break;
+ case 1:
+ printf("Partially caching GRP in RAM (%d KB/%d KB)\n", archive->cache_len / 1024, total / 1024);
+ break;
+ default:
+ printf("Not caching large GRP (%d KB)", total / 1024);
+ break;
+ }
+
+ uint8_t *crcBuffer = NULL;
+ /* we need a temporary buffer to calculate the CRC if it's not being cached */
+ if(!archive->cached)
+ crcBuffer = malloc(CRC_BUFLEN);
+ else
+ crcBuffer = archive->data;
+
+ int loop = 0;
+ int bytes = 0;
+ bool stop_inc = false;
+ while((j=read(archive->fileDescriptor, crcBuffer, CRC_BUFLEN))) {
+ archive->crc32 = crc32_update(crcBuffer,j,archive->crc32);
+
+ /* crcBuffer points to a permanent buffer */
+ if(archive->cached)
+ {
+ if(!stop_inc)
+ crcBuffer += j;
+
+ if(archive->cached == 1 && !stop_inc)
+ {
+ if(crcBuffer - archive->data >= archive->cache_len) /* we've read enough, further reads go into a temp buffer */
+ {
+ crcBuffer = malloc(CRC_BUFLEN);
+ stop_inc = true;
+ }
+ }
+ }
+
+ bytes += j;
+ loop++;
+
+ if(loop % 16 == 0)
+ printf("%d%% complete...\n", (int)(100.0 * bytes / (float)total)); // sorry
+ //rb->splashf(0, "point -%d", loop);
+ }
+
+ if(!archive->cached || stop_inc)
+ free(crcBuffer);
+
+ // The game layer seems to absolutely need to access an array int[4] groupefil_crc32
+ // so we need to store the crc32 in there too.
+ groupefil_crc32[grpSet.num] = archive->crc32;
+
+ //free(groupfil_memory[numgroupfiles]);
+ //groupfil_memory[numgroupfiles] = 0;
+
+ grpSet.num++;
+
+ return(grpSet.num-1);
+
+}
+
+void uninitgroupfile(void)
+{
+ int i;
+
+ for( i=0 ; i < grpSet.num ;i++){
+ close(grpSet.archives[i].fileDescriptor);
+ if(grpSet.archives[i].cached)
+ free(grpSet.archives[i].data);
+ free(grpSet.archives[i].gfilelist);
+ free(grpSet.archives[i].fileOffsets);
+ free(grpSet.archives[i].filesizes);
+ memset(&grpSet.archives[i], 0, sizeof(grpArchive_t));
+ }
+
+}
+
+void crc32_table_gen(unsigned int* crc32_table) /* build CRC32 table */
+{
+ unsigned int crc, poly;
+ int i, j;
+
+ poly = 0xEDB88320L;
+ for (i = 0; i < 256; i++)
+ {
+ crc = i;
+ for (j = 8; j > 0; j--)
+ {
+ if (crc & 1)
+ crc = (crc >> 1) ^ poly;
+ else
+ crc >>= 1;
+ }
+ crc32_table[i] = crc;
+ }
+}
+
+unsigned int crc32(uint8_t *buf, unsigned int length)
+{
+ unsigned int initial_crc;
+
+ initial_crc = 0;
+ return(crc32_update(buf, length, initial_crc));
+}
+
+uint32_t crc32_update(uint8_t *buf, uint32_t length, uint32_t crc_to_update)
+{
+ unsigned int crc32_table[256];
+
+ crc32_table_gen(crc32_table);
+
+ crc_to_update ^= 0xFFFFFFFF;
+
+ while (length--)
+ crc_to_update = crc32_table[(crc_to_update ^ *buf++) & 0xFF] ^ (crc_to_update >> 8);
+
+ return crc_to_update ^ 0xFFFFFFFF;
+}
+
+
+/*
+ * 16 12 5
+ * this is the CCITT CRC 16 polynomial X + X + X + 1.
+ * This is 0x1021 when x is 2, but the way the algorithm works
+ * we use 0x8408 (the reverse of the bit pattern). The high
+ * bit is always assumed to be set, thus we only use 16 bits to
+ * represent the 17 bit value.
+ */
+
+#define POLY 0x8408 /* 1021H bit reversed */
+
+uint16_t crc16(uint8_t *data_p, uint16_t length)
+{
+ uint8_t i;
+ unsigned int data;
+ unsigned int crc = 0xffff;
+
+ if (length == 0)
+ return (~crc);
+ do
+ {
+ for (i=0, data=(unsigned int)0xff & *data_p++;
+ i < 8;
+ i++, data >>= 1)
+ {
+ if ((crc & 0x0001) ^ (data & 0x0001))
+ crc = (crc >> 1) ^ POLY;
+ else crc >>= 1;
+ }
+ } while (--length);
+
+ crc = ~crc;
+ data = crc;
+ crc = (crc << 8) | (data >> 8 & 0xff);
+
+ return (crc);
+}
+
+// The engine can open files transparently on the filesystem or on the GRPsystem
+enum fileType_e{ SYSTEM_FILE, GRP_FILE} ;
+
+//An entry in the array tracking open files
+typedef struct openFile_s{
+ enum fileType_e type ;
+ int fd ; //Either the fileDescriptor or the fileIndex in a GRP depending on the type.
+ int cursor ; //lseek cursor
+ int grpID ; //GRP id
+ int used ; //Marker 1=used
+} openFile_t;
+
+
+#define MAXOPENFILES 64
+static openFile_t openFiles[MAXOPENFILES];
+
+int32_t kopen4load(const char *filename, int openOnlyFromGRP){
+
+ int32_t i, k;
+ int32_t newhandle;
+
+ grpArchive_t* archive;
+
+ //Search a free slot
+ newhandle = MAXOPENFILES-1;
+ while (openFiles[newhandle].used && newhandle >= 0)
+ newhandle--;
+
+
+ if (newhandle < 0)
+ Error(EXIT_FAILURE, "Too Many files open!\n");
+
+
+ //Try to look in the filesystem first. In this case fd = filedescriptor.
+ if(!openOnlyFromGRP){
+
+ openFiles[newhandle].fd = open(filename,O_BINARY|O_RDONLY);
+
+#if 0
+ if(openFiles[newhandle].fd < 0)
+ perror(filename);
+#endif
+ if (openFiles[newhandle].fd >= 0){
+ openFiles[newhandle].type = SYSTEM_FILE;
+ openFiles[newhandle].cursor = 0;
+ openFiles[newhandle].used = 1;
+ return(newhandle);
+ }
+ }
+
+ //Try to look in the GRP archives. In this case fd = index of the file in the GRP.
+ for(k=grpSet.num-1;k>=0;k--)
+ {
+ archive = &grpSet.archives[k];
+
+ for(i=archive->numFiles-1;i>=0;i--){
+
+ if (!strncasecmp((char*)archive->gfilelist[i],filename,12)){
+
+ openFiles[newhandle].type = GRP_FILE;
+ openFiles[newhandle].used = 1;
+ openFiles[newhandle].cursor = 0;
+ openFiles[newhandle].fd = i;
+ openFiles[newhandle].grpID = k;
+ LOGF("found GRP %s", filename);
+ return(newhandle);
+ }
+ }
+ }
+ LOGF("kopen4load: couldn't find %s in GRP", filename);
+
+ return(-1);
+
+}
+
+int32_t kread(int32_t handle, void *buffer, int32_t leng){
+
+ openFile_t * openFile ;
+ grpArchive_t * archive ;
+
+ openFile = &openFiles[handle];
+
+ if (!openFile->used){
+ printf("Invalide handle. Unrecoverable error.\n");
+ getchar();
+ exit(0);
+ }
+
+ //FILESYSTEM ? OS takes care of it !
+ if (openFile->type == SYSTEM_FILE){
+ return(read(openFile->fd,buffer,leng));
+ }
+
+ //File is actually in the GRP
+ archive = & grpSet.archives[openFile->grpID];
+
+ //Adjust leng so we cannot read more than filesystem-cursor location.
+ leng = min(leng,archive->filesizes[openFile->fd]-openFile->cursor);
+
+ if(!archive->cached)
+ {
+ lseek(archive->fileDescriptor,
+ archive->fileOffsets[openFile->fd] + openFile->cursor,
+ SEEK_SET);
+ leng = read(archive->fileDescriptor,buffer,leng);
+ }
+ else
+ {
+ if(archive->cached == 2) /* completely in RAM */
+ memcpy(buffer, archive->data + archive->fileOffsets[openFile->fd] + openFile->cursor, leng);
+ else
+ {
+ /* 3 cases here: either it's completely outside the cached region, in which case we
+ * fall back to a disk read; it can be on a boundary; or completely in RAM */
+ int ofs = archive->fileOffsets[openFile->fd];
+ int start = ofs + openFile->cursor;
+
+ /* completely outside */
+ if(start >= archive->cache_len)
+ {
+ lseek(archive->fileDescriptor,
+